0001: /* Soot - a J*va Optimization Framework
0002: * Copyright (C) 1999 Patrice Pominville
0003: *
0004: * This library is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU Lesser General Public
0006: * License as published by the Free Software Foundation; either
0007: * version 2.1 of the License, or (at your option) any later version.
0008: *
0009: * This library is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0012: * Lesser General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU Lesser General Public
0015: * License along with this library; if not, write to the
0016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
0017: * Boston, MA 02111-1307, USA.
0018: */
0019:
0020: /*
0021: * Modified by the Sable Research Group and others 1997-1999.
0022: * See the 'credits' file distributed with Soot for the complete list of
0023: * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
0024: */
0025:
0026: package soot.baf.toolkits.base;
0027:
0028: import soot.options.*;
0029:
0030: import soot.util.*;
0031: import java.util.*;
0032: import soot.*;
0033: import soot.baf.*;
0034: import soot.toolkits.scalar.*;
0035: import soot.toolkits.graph.*;
0036:
0037: public class LoadStoreOptimizer extends BodyTransformer {
0038: public LoadStoreOptimizer(Singletons.Global g) {
0039: }
0040:
0041: public static LoadStoreOptimizer v() {
0042: return G.v().soot_baf_toolkits_base_LoadStoreOptimizer();
0043: }
0044:
0045: // Constants
0046: boolean debug = false;
0047:
0048: // constants returned by the stackIndependent function.
0049: final static private int FAILURE = 0;
0050: final static private int SUCCESS = 1;
0051: final static private int MAKE_DUP = 2;
0052: final static private int MAKE_DUP1_X1 = 3;
0053: final static private int SPECIAL_SUCCESS = 4;
0054: final static private int HAS_CHANGED = 5;
0055: final static private int SPECIAL_SUCCESS2 = 6;
0056:
0057: final static private int STORE_LOAD_ELIMINATION = 0;
0058: final static private int STORE_LOAD_LOAD_ELIMINATION = -1;
0059:
0060: private Map gOptions;
0061:
0062: /** The method that drives the optimizations. */
0063: /* This is the public interface to LoadStoreOptimizer */
0064:
0065: protected void internalTransform(Body body, String phaseName,
0066: Map options) {
0067:
0068: gOptions = options;
0069:
0070: Instance instance = new Instance();
0071: instance.mBody = body;
0072: instance.mUnits = body.getUnits();
0073:
0074: debug = PhaseOptions.getBoolean(gOptions, "debug");
0075:
0076: if (Options.v().verbose())
0077: G.v().out.println("[" + body.getMethod().getName()
0078: + "] Performing LoadStore optimizations...");
0079:
0080: if (debug) {
0081: G.v().out.println("\n\nOptimizing Method: "
0082: + body.getMethod().getName());
0083: }
0084:
0085: instance.go();
0086: }
0087:
0088: class Instance {
0089: // Instance vars.
0090: private Chain mUnits;
0091: private Body mBody;
0092: private ExceptionalUnitGraph mExceptionalUnitGraph;
0093: private LocalDefs mLocalDefs;
0094: private LocalUses mLocalUses;
0095: private Map<Unit, Block> mUnitToBlockMap; // maps a unit it's containing block
0096: private boolean mPass2 = false;
0097:
0098: void go() {
0099: if (!mUnits.isEmpty()) {
0100: buildUnitToBlockMap();
0101: computeLocalDefsAndLocalUsesInfo();
0102:
0103: if (debug) {
0104: G.v().out.println("Calling optimizeLoadStore(1)\n");
0105: }
0106: optimizeLoadStores();
0107:
0108: if (PhaseOptions.getBoolean(gOptions, "inter")) {
0109: if (debug) {
0110: G.v().out
0111: .println("Calling doInterBlockOptimizations");
0112: }
0113: doInterBlockOptimizations();
0114:
0115: //computeLocalDefsAndLocalUsesInfo();
0116: //propagateLoadsBackwards(); if(debug) G.v().out.println("pass 3");
0117: //optimizeLoadStores(); if(debug) G.v().out.println("pass 4");
0118: //propagateLoadsForward(); if(debug) G.v().out.println("pass 5");
0119: //propagateBackwardsIndependentHunk(); if(debug) G.v().out.println("pass 6");
0120: }
0121:
0122: if (PhaseOptions.getBoolean(gOptions, "sl2")
0123: || PhaseOptions.getBoolean(gOptions, "sll2")) {
0124: mPass2 = true;
0125: if (debug) {
0126: G.v().out
0127: .println("Calling optimizeLoadStore(2)");
0128: }
0129: optimizeLoadStores();
0130: }
0131: }
0132: }
0133:
0134: /*
0135: * Computes a map binding each unit in a method to the unique basic block
0136: * that contains it.
0137: */
0138: private void buildUnitToBlockMap() {
0139: BlockGraph blockGraph = new ZonedBlockGraph(mBody);
0140: if (debug) {
0141: G.v().out.println("Method "
0142: + mBody.getMethod().getName()
0143: + " Block Graph: ");
0144: G.v().out.println(blockGraph);
0145: }
0146:
0147: List blocks = blockGraph.getBlocks();
0148: mUnitToBlockMap = new HashMap<Unit, Block>();
0149:
0150: Iterator blockIt = blocks.iterator();
0151: while (blockIt.hasNext()) {
0152: Block block = (Block) blockIt.next();
0153:
0154: Iterator unitIt = block.iterator();
0155: while (unitIt.hasNext()) {
0156: Unit unit = (Unit) unitIt.next();
0157: mUnitToBlockMap.put(unit, block);
0158: }
0159: }
0160: }
0161:
0162: // computes a list of all the stores in mUnits in order of their occurence therein.
0163:
0164: private List<Unit> buildStoreList() {
0165: Iterator it = mUnits.iterator();
0166: List<Unit> storeList = new ArrayList<Unit>();
0167:
0168: while (it.hasNext()) {
0169: Unit unit = (Unit) it.next();
0170: if (unit instanceof StoreInst)
0171: storeList.add(unit);
0172: }
0173: return storeList;
0174: }
0175:
0176: private void computeLocalDefsAndLocalUsesInfo() {
0177: mExceptionalUnitGraph = new ExceptionalUnitGraph(mBody);
0178: mLocalDefs = new SmartLocalDefs(mExceptionalUnitGraph,
0179: new SimpleLiveLocals(mExceptionalUnitGraph));
0180: mLocalUses = new SimpleLocalUses(mExceptionalUnitGraph,
0181: mLocalDefs);
0182: }
0183:
0184: // main optimizing method
0185: private void optimizeLoadStores() {
0186: List<Unit> storeList;
0187:
0188: // build a list of all store units in mUnits
0189: storeList = buildStoreList();
0190:
0191: // Eliminate store/load
0192: {
0193:
0194: boolean hasChanged = true;
0195:
0196: boolean hasChangedFlag = false;
0197: while (hasChanged) {
0198:
0199: hasChanged = false;
0200:
0201: // Iterate over the storeList
0202: Iterator<Unit> unitIt = storeList.iterator();
0203:
0204: nextUnit: while (unitIt.hasNext()) {
0205: Unit unit = unitIt.next();
0206: List uses = mLocalUses.getUsesOf(unit);
0207:
0208: // if uses of a store < 3, attempt some form of store/load elimination
0209: if (uses.size() < 3) {
0210:
0211: // check that all uses have only the current store as their definition
0212: {
0213: Iterator useIt = uses.iterator();
0214: while (useIt.hasNext()) {
0215: UnitValueBoxPair pair = (UnitValueBoxPair) useIt
0216: .next();
0217: Unit loadUnit = pair.getUnit();
0218: if (!(loadUnit instanceof LoadInst))
0219: continue nextUnit;
0220:
0221: List<Unit> defs = mLocalDefs
0222: .getDefsOfAt((Local) pair
0223: .getValueBox()
0224: .getValue(),
0225: loadUnit);
0226: if (defs.size() > 1) {
0227: continue nextUnit;
0228: } else if (defs.get(0) != unit) {
0229: continue nextUnit; // xxx how can you get here?
0230: }
0231: }
0232: }
0233:
0234: // Check that all loads are in the same bb as the store
0235: {
0236: Block storeBlock = mUnitToBlockMap
0237: .get(unit);
0238:
0239: Iterator useIt = uses.iterator();
0240: while (useIt.hasNext()) {
0241: UnitValueBoxPair pair = (UnitValueBoxPair) useIt
0242: .next();
0243: Block useBlock = mUnitToBlockMap
0244: .get(pair.getUnit());
0245: if (useBlock != storeBlock)
0246: continue nextUnit;
0247: }
0248: }
0249:
0250: // Check for stack independance (automatic reordering may be performed by stackIndependent() fcnt)
0251: {
0252: Block block;
0253: switch (uses.size()) {
0254: case 0: /*
0255: if(Options.getBoolean(gOptions, "s-elimination")) {
0256: // replace store by a pop and remove store from store list
0257: replaceUnit(unit, Baf.v().newPopInst(((StoreInst)unit).getOpType()));
0258: unitIt.remove();
0259:
0260: hasChanged = true; hasChangedFlag = false;
0261: }*/
0262: break;
0263:
0264: case 1:
0265: if (PhaseOptions.getBoolean(
0266: gOptions, "sl")) {
0267: if (!mPass2
0268: || PhaseOptions
0269: .getBoolean(
0270: gOptions,
0271: "sl2")) {
0272: // try to eliminate store/load pair
0273: Unit loadUnit = ((UnitValueBoxPair) uses
0274: .get(0)).getUnit();
0275: block = mUnitToBlockMap
0276: .get(unit);
0277: int test = stackIndependent(
0278: unit, loadUnit,
0279: block,
0280: STORE_LOAD_ELIMINATION);
0281:
0282: //xxx
0283: //if(block.getIndexInMethod() < 1 ) { // <13
0284: if (test == SUCCESS
0285: || test == SPECIAL_SUCCESS) {
0286:
0287: block.remove(unit);
0288: block.remove(loadUnit);
0289: unitIt.remove();
0290: hasChanged = true;
0291: hasChangedFlag = false;
0292:
0293: //delme[
0294: if (debug) {
0295: G.v().out
0296: .println("Store/Load elimination occurred case1.");
0297: }
0298: //delme]
0299: } /*else if (test == SPECIAL_SUCCESS2) {
0300: if(!hasChangedFlag) {
0301: hasChangedFlag = true;
0302: hasChanged = true;
0303: }
0304: }*/
0305: }
0306: }
0307: break;
0308:
0309: case 2:
0310: if (PhaseOptions.getBoolean(
0311: gOptions, "sll")) {
0312: if (!mPass2
0313: || PhaseOptions
0314: .getBoolean(
0315: gOptions,
0316: "sll2")) {
0317: // try to replace store/load/load trio by a flavor of the dup unit
0318: Unit firstLoad = ((UnitValueBoxPair) uses
0319: .get(0)).getUnit();
0320: Unit secondLoad = ((UnitValueBoxPair) uses
0321: .get(1)).getUnit();
0322: block = mUnitToBlockMap
0323: .get(unit);
0324:
0325: Unit temp; // xxx try to optimize this
0326: if (mUnits.follows(
0327: firstLoad,
0328: secondLoad)) {
0329: temp = secondLoad;
0330: secondLoad = firstLoad;
0331: firstLoad = temp;
0332: }
0333:
0334: int result = stackIndependent(
0335: unit, firstLoad,
0336: block,
0337: STORE_LOAD_ELIMINATION);
0338: if (result == SUCCESS) {
0339:
0340: // move the first load just after its defining store.
0341: block.remove(firstLoad);
0342: block
0343: .insertAfter(
0344: firstLoad,
0345: unit);
0346:
0347: int res = stackIndependent(
0348: unit,
0349: secondLoad,
0350: block,
0351: STORE_LOAD_LOAD_ELIMINATION);
0352: if (res == MAKE_DUP) {
0353: // replace store by dup, drop both loads
0354: Dup1Inst dup = Baf
0355: .v()
0356: .newDup1Inst(
0357: ((LoadInst) secondLoad)
0358: .getOpType());
0359: dup
0360: .addAllTagsOf(unit);
0361: replaceUnit(unit,
0362: dup);
0363: unitIt.remove(); // remove store from store list
0364:
0365: block
0366: .remove(firstLoad);
0367: block
0368: .remove(secondLoad);
0369:
0370: hasChanged = true;
0371: hasChangedFlag = false;
0372:
0373: } /* else if(res == MAKE_DUP1_X1) {
0374:
0375: // replace store/load/load by a dup1_x1
0376: Unit stackUnit = getStackItemAt2(unit, block, -2);
0377:
0378: if(stackUnit instanceof PushInst)
0379: break;
0380:
0381: Type underType = type(stackUnit);
0382: if(underType == null) {
0383: throw new RuntimeException("this has to be corrected (loadstoroptimiser.java)" + stackUnit);
0384: }
0385:
0386: if(debug) { G.v().out.println("stack unit is: " + stackUnit + " stack type is " + underType);}
0387: replaceUnit(unit, Baf.v().newDup1_x1Inst(((LoadInst) secondLoad).getOpType(),underType));
0388: unitIt.remove();
0389:
0390: block.remove(firstLoad);
0391: block.remove(secondLoad);
0392:
0393: hasChanged = true; hasChangedFlag = false;
0394: break;
0395:
0396: } */
0397:
0398: } else if (result == SPECIAL_SUCCESS
0399: || result == HAS_CHANGED
0400: || result == SPECIAL_SUCCESS2) {
0401: if (!hasChangedFlag) {
0402: hasChangedFlag = true;
0403: hasChanged = true;
0404: }
0405: }
0406: }
0407:
0408: }
0409: }
0410: }
0411: }
0412: }
0413: }
0414: }
0415: }
0416:
0417: /**
0418: * Checks if the units occuring between [from, to] consume
0419: *. stack items not produced by these interval units. (ie if the
0420: * stack height ever goes negative between from and to, assuming the
0421: * stack height is set to 0 upon executing the instruction following 'from'.
0422: *
0423: */
0424: private boolean isRequiredByFollowingUnits(Unit from, Unit to) {
0425: Iterator it = mUnits.iterator(from, to);
0426: int stackHeight = 0;
0427: boolean res = false;
0428:
0429: if (from != to) {
0430: // advance past the 'from' unit
0431: it.next();
0432: while (it.hasNext()) {
0433: Unit currentInst = (Unit) it.next();
0434: if (currentInst == to)
0435: break;
0436:
0437: stackHeight -= ((Inst) currentInst).getInCount();
0438: if (stackHeight < 0) {
0439: res = true;
0440: break;
0441: }
0442: stackHeight += ((Inst) currentInst).getOutCount();
0443: }
0444: }
0445: return res;
0446: }
0447:
0448: private int pushStoreToLoad(Unit from, Unit to, Block block) {
0449: Unit storePred = block.getPredOf(from);
0450: if (storePred != null) {
0451: if (((Inst) storePred).getOutCount() == 1) {
0452: Set<Unit> unitsToMove = new HashSet<Unit>();
0453: unitsToMove.add(storePred);
0454: unitsToMove.add(from);
0455: int h = ((Inst) storePred).getInCount();
0456: Unit currentUnit = storePred;
0457: if (h != 0) {
0458: currentUnit = block.getPredOf(storePred);
0459: while (currentUnit != null) {
0460:
0461: h -= ((Inst) currentUnit).getOutCount();
0462: if (h < 0) { // xxx could be more flexible here?
0463: if (debug) {
0464: G.v().out.println("xxx: negative");
0465: }
0466: return FAILURE;
0467: }
0468: h += ((Inst) currentUnit).getInCount();
0469: unitsToMove.add(currentUnit);
0470: if (h == 0)
0471: break;
0472: currentUnit = block.getPredOf(currentUnit);
0473: }
0474: }
0475: if (currentUnit == null) {
0476: if (debug) {
0477: G.v().out.println("xxx: null");
0478: }
0479: return FAILURE;
0480: }
0481:
0482: Unit uu = from;
0483: for (;;) {
0484: uu = block.getSuccOf(uu);
0485: if (uu == to)
0486: break;
0487: Iterator<Unit> it2 = unitsToMove.iterator();
0488: while (it2.hasNext()) {
0489: Unit nu = it2.next();
0490: if (debug) {
0491: G.v().out
0492: .println("xxxspecial;success pushing forward stuff.");
0493: }
0494:
0495: if (!canMoveUnitOver(nu, uu)) {
0496: if (debug) {
0497: G.v().out
0498: .println("xxx: cant move over faillure"
0499: + nu);
0500: }
0501: return FAILURE;
0502: }
0503: if (debug) {
0504: G.v().out.println("can move" + nu
0505: + " over " + uu);
0506: }
0507: }
0508: }
0509:
0510: // if we get here it means we can move all the units in the set pass the units in between [to, from]
0511: Unit unitToMove = currentUnit;
0512: while (unitToMove != from) {
0513: Unit succ = block.getSuccOf(unitToMove);
0514: if (debug) {
0515: G.v().out.println("moving " + unitToMove);
0516: }
0517: block.remove(unitToMove);
0518: block.insertBefore(unitToMove, to);
0519: unitToMove = succ;
0520: }
0521: block.remove(from);
0522: block.insertBefore(from, to);
0523:
0524: if (debug) {
0525: G.v().out
0526: .println("xxx1success pushing forward stuff.");
0527: }
0528: return SPECIAL_SUCCESS;
0529: }
0530: }
0531:
0532: return FAILURE;
0533: }
0534:
0535: /**
0536: *
0537: *
0538: * @return FAILURE when store load elimination is not possible in any form.
0539: * @return SUCCESS when a load in a store load pair can be moved IMMEDIATELY after it's defining store
0540: * @return MAKE_DUP when a store/load/load trio can be replaced by a dup unit.
0541: * @return MAKE_DUP_X1 when store/load/load trio can be replaced by a dup1_x1 unit
0542: * @return SPECIAL_SUCCESS when a store/load pair can AND must be immediately annihilated.
0543: * @return HAS_CHANGED when store load elimination is not possible in any form, but some unit reordering has occured
0544: */
0545:
0546: private int stackIndependent(Unit from, Unit to, Block block,
0547: int aContext) {
0548: if (debug) {
0549: G.v().out.println("Trying: " + from + "/" + to
0550: + " in block " + block.getIndexInMethod()
0551: + ":");
0552: G.v().out
0553: .println("context:"
0554: + (aContext == STORE_LOAD_ELIMINATION ? "STORE_LOAD_ELIMINATION"
0555: : "STORE_LOAD_LOAD_ELIMINATION"));
0556: }
0557:
0558: int minStackHeightAttained = 0; // records the min stack height attained between [from, to]
0559: int stackHeight = 0; // records the stack height when similating the effects on the stack
0560: Iterator it = mUnits.iterator(mUnits.getSuccOf(from));
0561: int res = FAILURE;
0562:
0563: Unit currentInst = (Unit) it.next(); // get unit following the store
0564:
0565: if (aContext == STORE_LOAD_LOAD_ELIMINATION) {
0566: currentInst = (Unit) it.next(); // jump after first load
0567: }
0568:
0569: // find minStackHeightAttained
0570: while (currentInst != to) {
0571: stackHeight -= ((Inst) currentInst).getInCount();
0572: if (stackHeight < minStackHeightAttained)
0573: minStackHeightAttained = stackHeight;
0574:
0575: stackHeight += ((Inst) currentInst).getOutCount();
0576:
0577: currentInst = (Unit) it.next();
0578: }
0579:
0580: // note: now stackHeight contains the delta height of the stack after executing the units contained in
0581: // [from, to] non-inclusive.
0582:
0583: if (debug) {
0584: G.v().out.println("nshv = " + stackHeight);
0585: G.v().out.println("mshv = " + minStackHeightAttained);
0586: }
0587:
0588: boolean hasChanged = true;
0589:
0590: // Iterate until an elimination clause is taken or no reordering of the code occurs
0591: while (hasChanged) {
0592: hasChanged = false;
0593:
0594: // check for possible sll elimination
0595: if (aContext == STORE_LOAD_LOAD_ELIMINATION) {
0596:
0597: if (stackHeight == 0 && minStackHeightAttained == 0) {
0598: if (debug) {
0599: G.v().out
0600: .println("xxx: succ: -1, makedup ");
0601: }
0602: return MAKE_DUP;
0603: } else if (stackHeight == -1
0604: && minStackHeightAttained == -1) {
0605: if (debug) {
0606: G.v().out
0607: .println("xxx: succ: -1, makedup , -1");
0608: }
0609: return MAKE_DUP;
0610: } else if (stackHeight == -2
0611: && minStackHeightAttained == -2) {
0612: if (debug) {
0613: G.v().out
0614: .println("xxx: succ -1 , make dupx1 ");
0615: }
0616: return MAKE_DUP1_X1;
0617: }
0618:
0619: else if (minStackHeightAttained < -2) {
0620: if (debug) {
0621: G.v().out
0622: .println("xxx: failled due: minStackHeightAttained < -2 ");
0623: }
0624: return FAILURE;
0625: }
0626: }
0627:
0628: // check for possible sl elimination
0629: if (aContext == STORE_LOAD_ELIMINATION) {
0630: if (stackHeight == 0 && minStackHeightAttained == 0) {
0631: if (debug) {
0632: G.v().out
0633: .println("xxx: success due: 0, SUCCESS ");
0634: }
0635: return SUCCESS;
0636: }
0637: /* xxx broken data depensie problem.
0638: else if (minStackHeightAttained == -1 && stackHeight == -1) { // try to make it more generic
0639: Unit u = (Unit) block.getPredOf(from);
0640: if(u instanceof FieldGetInst)
0641: if(block.getPredOf(u) instanceof Dup1Inst) {
0642: block.remove(u);
0643: block.insertBefore(u, to);
0644: block.remove(from);
0645: block.insertBefore(from, to);
0646: if(debug) { G.v().out.println("xxx: success due to 1, SPECIAL_SUCCESS2");}
0647: return SPECIAL_SUCCESS2;
0648: }
0649: }*/
0650: else if (minStackHeightAttained < 0) {
0651: return pushStoreToLoad(from, to, block);
0652: }
0653: }
0654:
0655: it = mUnits.iterator(mUnits.getSuccOf(from), to);
0656:
0657: Unit unitToMove = null;
0658: Unit u = (Unit) it.next();
0659:
0660: if (aContext == STORE_LOAD_LOAD_ELIMINATION) {
0661: u = (Unit) it.next();
0662: }
0663: int currentH = 0;
0664:
0665: // find a candidate to move before the store/load/(load) group
0666: while (u != to) {
0667:
0668: if (((Inst) u).getNetCount() == 1) {
0669: // xxx remove this check
0670: if (u instanceof LoadInst
0671: || u instanceof PushInst
0672: || u instanceof NewInst
0673: || u instanceof StaticGetInst
0674: || u instanceof Dup1Inst) {
0675:
0676: // verify that unitToMove is not required by following units (until the 'to' unit)
0677: if (!isRequiredByFollowingUnits(u, to)) {
0678: unitToMove = u;
0679: }
0680:
0681: } else {
0682: if (debug) {
0683: G.v().out
0684: .println("1003:(LoadStoreOptimizer@stackIndependent): found unknown unit w/ getNetCount == 1"
0685: + u);
0686: }
0687: }
0688: }
0689:
0690: if (unitToMove != null) {
0691: int flag = 0;
0692: //if(aContext == 0 || !(stackHeight > -2 && minStackHeightAttained == -2 ) ) {
0693:
0694: if (tryToMoveUnit(unitToMove, block, from, to,
0695: flag)) {
0696: if (stackHeight > -2
0697: && minStackHeightAttained == -2) {
0698: return HAS_CHANGED;
0699: }
0700:
0701: stackHeight--;
0702: if (stackHeight < minStackHeightAttained)
0703: minStackHeightAttained = stackHeight;
0704: hasChanged = true;
0705: break;
0706: }
0707: }
0708:
0709: currentH += ((Inst) u).getNetCount();
0710: unitToMove = null;
0711: u = (Unit) it.next();
0712: }
0713: }
0714:
0715: if (isCommutativeBinOp(block.getSuccOf(to))) {
0716: if (aContext == STORE_LOAD_ELIMINATION
0717: && stackHeight == 1
0718: && minStackHeightAttained == 0) {
0719: if (debug) {
0720: G.v().out.println("xxx: commutative ");
0721: }
0722: return SPECIAL_SUCCESS;
0723: } else if (((Inst) to).getOutCount() == 1
0724: && ((Inst) to).getInCount() == 0
0725: && ((Inst) mUnits.getPredOf(to)).getOutCount() == 1
0726: && ((Inst) mUnits.getPredOf(to)).getInCount() == 0) {
0727:
0728: Object toPred = mUnits.getPredOf(to);
0729: block.remove((Unit) toPred);
0730: block.insertAfter((Unit) toPred, to);
0731: return HAS_CHANGED; // return has changed
0732: } else
0733: return FAILURE;
0734: }
0735: if (aContext == STORE_LOAD_ELIMINATION)
0736: return pushStoreToLoad(from, to, block);
0737:
0738: return res;
0739: }
0740:
0741: /**
0742: * @return true if aUnit perform a non-local read or write. false otherwise.
0743: */
0744: private boolean isNonLocalReadOrWrite(Unit aUnit) {
0745: if ((aUnit instanceof FieldArgInst)
0746: || (aUnit instanceof ArrayReadInst)
0747: || (aUnit instanceof ArrayWriteInst))
0748: return true;
0749: else
0750: return false;
0751: }
0752:
0753: /**
0754: * When reordering bytecode, check if it is safe to move aUnitToMove past aUnitToGoOver.
0755: * @return true if aUnitToMove can be moved past aUnitToGoOver.
0756: */
0757: private boolean canMoveUnitOver(Unit aUnitToMove,
0758: Unit aUnitToGoOver) // xxx missing cases
0759: {
0760:
0761: // can't change method call order or change fieldargInst and method call order
0762: if ((aUnitToGoOver instanceof MethodArgInst && aUnitToMove instanceof MethodArgInst)
0763: || (aUnitToGoOver instanceof MethodArgInst && isNonLocalReadOrWrite(aUnitToMove))
0764: || (isNonLocalReadOrWrite(aUnitToGoOver) && aUnitToMove instanceof MethodArgInst)
0765: ||
0766:
0767: (aUnitToGoOver instanceof ArrayReadInst && aUnitToMove instanceof ArrayWriteInst)
0768: || (aUnitToGoOver instanceof ArrayWriteInst && aUnitToMove instanceof ArrayReadInst)
0769: || (aUnitToGoOver instanceof ArrayWriteInst && aUnitToMove instanceof ArrayWriteInst)
0770: ||
0771:
0772: (aUnitToGoOver instanceof FieldPutInst
0773: && aUnitToMove instanceof FieldGetInst && ((FieldArgInst) aUnitToGoOver)
0774: .getField() == ((FieldArgInst) aUnitToMove)
0775: .getField())
0776: || (aUnitToGoOver instanceof FieldGetInst
0777: && aUnitToMove instanceof FieldPutInst && ((FieldArgInst) aUnitToGoOver)
0778: .getField() == ((FieldArgInst) aUnitToMove)
0779: .getField())
0780: || (aUnitToGoOver instanceof FieldPutInst
0781: && aUnitToMove instanceof FieldPutInst && ((FieldArgInst) aUnitToGoOver)
0782: .getField() == ((FieldArgInst) aUnitToMove)
0783: .getField())
0784: ||
0785:
0786: (aUnitToGoOver instanceof StaticPutInst
0787: && aUnitToMove instanceof StaticGetInst && ((FieldArgInst) aUnitToGoOver)
0788: .getField() == ((FieldArgInst) aUnitToMove)
0789: .getField())
0790: || (aUnitToGoOver instanceof StaticGetInst
0791: && aUnitToMove instanceof StaticPutInst && ((FieldArgInst) aUnitToGoOver)
0792: .getField() == ((FieldArgInst) aUnitToMove)
0793: .getField())
0794: || (aUnitToGoOver instanceof StaticPutInst
0795: && aUnitToMove instanceof StaticPutInst && ((FieldArgInst) aUnitToGoOver)
0796: .getField() == ((FieldArgInst) aUnitToMove)
0797: .getField()))
0798: return false;
0799:
0800: // xxx to be safe don't mess w/ monitors. These rules could be relaxed. ? Maybe.
0801: if (aUnitToGoOver instanceof EnterMonitorInst
0802: || aUnitToGoOver instanceof ExitMonitorInst)
0803: return false;
0804:
0805: if (aUnitToMove instanceof EnterMonitorInst
0806: || aUnitToGoOver instanceof ExitMonitorInst)
0807: return false;
0808:
0809: if (aUnitToGoOver instanceof IdentityInst
0810: || aUnitToMove instanceof IdentityInst)
0811: return false;
0812:
0813: if (aUnitToMove instanceof LoadInst) {
0814: if (aUnitToGoOver instanceof StoreInst) {
0815: if (((StoreInst) aUnitToGoOver).getLocal() == ((LoadInst) aUnitToMove)
0816: .getLocal()) {
0817: return false;
0818: }
0819: } else if (aUnitToGoOver instanceof IncInst) {
0820: if (((IncInst) aUnitToGoOver).getLocal() == ((LoadInst) aUnitToMove)
0821: .getLocal()) {
0822: return false;
0823: }
0824: }
0825: }
0826:
0827: // don't move def of load pass it.
0828: if (aUnitToMove instanceof StoreInst) {
0829: if (aUnitToGoOver instanceof LoadInst) {
0830: if (((LoadInst) aUnitToGoOver).getLocal() == ((StoreInst) aUnitToMove)
0831: .getLocal()) {
0832: return false;
0833: }
0834: } else if (aUnitToGoOver instanceof IncInst) {
0835: if (((IncInst) aUnitToGoOver).getLocal() == ((StoreInst) aUnitToMove)
0836: .getLocal()) {
0837: return false;
0838: }
0839: }
0840: }
0841:
0842: if (aUnitToMove instanceof IncInst) {
0843: if (aUnitToGoOver instanceof StoreInst) {
0844: if (((StoreInst) aUnitToGoOver).getLocal() == ((IncInst) aUnitToMove)
0845: .getLocal()) {
0846: return false;
0847: }
0848: } else if (aUnitToGoOver instanceof LoadInst) {
0849: if (((LoadInst) aUnitToGoOver).getLocal() == ((IncInst) aUnitToMove)
0850: .getLocal()) {
0851: return false;
0852: }
0853: }
0854: }
0855: return true;
0856: }
0857:
0858: private boolean tryToMoveUnit(Unit unitToMove, Block block,
0859: Unit from, Unit to, int flag) {
0860:
0861: int h = 0;
0862: Unit current = unitToMove;
0863: boolean reachedStore = false;
0864: boolean reorderingOccurred = false;
0865:
0866: if (debug) {
0867: G.v().out.println("[tryToMoveUnit]: trying to move:"
0868: + unitToMove);
0869: }
0870: if (unitToMove == null)
0871: return false;
0872:
0873: while (current != block.getHead()) { // do not go past basic block limit
0874: current = (Unit) mUnits.getPredOf(current);
0875:
0876: if (!canMoveUnitOver(current, unitToMove))
0877: return false;
0878:
0879: if (current == from)
0880: reachedStore = true;
0881:
0882: h -= ((Inst) current).getOutCount();
0883: if (h < 0) {
0884: if (debug) {
0885: G.v().out
0886: .println("1006:(LoadStoreOptimizer@stackIndependent): Stack went negative while trying to reorder code.");
0887: }
0888:
0889: if (flag == 1) {
0890: if (current instanceof DupInst) {
0891: block.remove(unitToMove);
0892: block.insertAfter(unitToMove, current);
0893: // block.insertAfter( new BSwapInst( ) ,unitToMove);
0894: }
0895:
0896: }
0897: return false;
0898: }
0899: h += ((Inst) current).getInCount();
0900:
0901: if (h == 0 && reachedStore == true) {
0902: if (!isRequiredByFollowingUnits(unitToMove, to)) {
0903: if (debug) {
0904: G.v().out
0905: .println("10077:(LoadStoreOptimizer@stackIndependent): reordering bytecode move: "
0906: + unitToMove
0907: + "before: "
0908: + current);
0909: }
0910: block.remove(unitToMove);
0911: block.insertBefore(unitToMove, current);
0912:
0913: reorderingOccurred = true;
0914: break;
0915: }
0916: }
0917: }
0918:
0919: if (reorderingOccurred) {
0920: if (debug) {
0921: G.v().out.println("reordering occured");
0922: }
0923: return true;
0924: } else {
0925: if (debug) {
0926: G.v().out
0927: .println("1008:(LoadStoreOptimizer@stackIndependent):failled to find a new slot for unit to move");
0928: }
0929: return false;
0930: }
0931: }
0932:
0933: /**
0934: * Replace 1 or 2 units by a third unit in a block. Both units to
0935: * replace should be in the same block. The map 'mUnitToBlockMap'
0936: * is updated. The replacement unit is inserted in the position,
0937: * of the aToReplace2 if not null, otherwise in aToReplace1's slot.
0938: *
0939: * @param aToReplace1 Unit to replace. (shouldn't be null)
0940: * @param aToReplace2 Second Unit to replace (can be null)
0941: * @param aReplacement Unit that replaces the 2 previous units (shouldn't be null)
0942: */
0943: private void replaceUnit(Unit aToReplace1, Unit aToReplace2,
0944: Unit aReplacement) {
0945: Block block = mUnitToBlockMap.get(aToReplace1);
0946:
0947: if (aToReplace2 != null) {
0948: block.insertAfter(aReplacement, aToReplace2);
0949: block.remove(aToReplace2);
0950: } else {
0951: block.insertAfter(aReplacement, aToReplace1);
0952: }
0953:
0954: block.remove(aToReplace1);
0955:
0956: // add the new unit the block map
0957: mUnitToBlockMap.put(aReplacement, block);
0958: }
0959:
0960: private void replaceUnit(Unit aToReplace, Unit aReplacement) {
0961: replaceUnit(aToReplace, null, aReplacement);
0962: }
0963:
0964: /*
0965: * @param some block
0966: * @return true if the block is an exception handler.
0967: */
0968: private boolean isExceptionHandlerBlock(Block aBlock) {
0969: Unit blockHead = aBlock.getHead();
0970: Iterator it = mBody.getTraps().iterator();
0971: while (it.hasNext()) {
0972: Trap trap = (Trap) it.next();
0973: if (trap.getHandlerUnit() == blockHead)
0974: return true;
0975: }
0976: return false;
0977: }
0978:
0979: // not a save function :: goes over block boundries
0980: private int getDeltaStackHeightFromTo(Unit aFrom, Unit aTo) {
0981: Iterator it = mUnits.iterator(aFrom, aTo);
0982: int h = 0;
0983:
0984: while (it.hasNext()) {
0985: h += ((Inst) it.next()).getNetCount();
0986: }
0987:
0988: return h;
0989: }
0990:
0991: /**
0992: * Performs 2 simple inter-block optimizations in order to keep
0993: * some variables on the stack between blocks. Both are intented to catch
0994: * 'if' like constructs where the control flow branches temporarely into two paths
0995: * that join up at a latter point.
0996: *
0997: */
0998: private void doInterBlockOptimizations() {
0999: boolean hasChanged = true;
1000: while (hasChanged) {
1001: hasChanged = false;
1002:
1003: List<Unit> tempList = new ArrayList<Unit>();
1004: tempList.addAll(mUnits);
1005: Iterator<Unit> it = tempList.iterator();
1006: while (it.hasNext()) {
1007: Unit u = it.next();
1008:
1009: if (u instanceof LoadInst) {
1010: if (debug) {
1011: G.v().out.println("inter trying: " + u);
1012: }
1013: Block loadBlock = mUnitToBlockMap.get(u);
1014: List<Unit> defs = mLocalDefs.getDefsOfAt(
1015: ((LoadInst) u).getLocal(), u);
1016:
1017: // first optimization
1018: if (defs.size() == 1) {
1019: Block defBlock = mUnitToBlockMap.get(defs
1020: .get(0));
1021: if (defBlock != loadBlock
1022: && !(isExceptionHandlerBlock(loadBlock))) {
1023: Unit storeUnit = defs.get(0);
1024: if (storeUnit instanceof StoreInst) {
1025: List uses = mLocalUses
1026: .getUsesOf(storeUnit);
1027: if (uses.size() == 1) {
1028: if (allSuccesorsOfAreThePredecessorsOf(
1029: defBlock, loadBlock)) {
1030: if (getDeltaStackHeightFromTo(
1031: defBlock
1032: .getSuccOf(storeUnit),
1033: defBlock.getTail()) == 0) {
1034: Iterator it2 = defBlock
1035: .getSuccs()
1036: .iterator();
1037: boolean res = true;
1038: while (it2.hasNext()) {
1039: Block b = (Block) it2
1040: .next();
1041: if (getDeltaStackHeightFromTo(
1042: b.getHead(),
1043: b.getTail()) != 0) {
1044: res = false;
1045: break;
1046: }
1047: if (b.getPreds()
1048: .size() != 1
1049: || b
1050: .getSuccs()
1051: .size() != 1) {
1052: res = false;
1053: break;
1054: }
1055: }
1056: if (debug) {
1057: G.v().out
1058: .println(defBlock
1059: .toString()
1060: + loadBlock
1061: .toString());
1062: }
1063:
1064: if (res) {
1065: defBlock
1066: .remove(storeUnit);
1067: mUnitToBlockMap
1068: .put(
1069: storeUnit,
1070: loadBlock);
1071: loadBlock
1072: .insertBefore(
1073: storeUnit,
1074: loadBlock
1075: .getHead());
1076: hasChanged = true;
1077: if (debug) {
1078: G.v().out
1079: .println("inter-block opti occurred "
1080: + storeUnit
1081: + " "
1082: + u);
1083: }
1084: if (debug) {
1085: G.v().out
1086: .println(defBlock
1087: .toString()
1088: + loadBlock
1089: .toString());
1090: }
1091: }
1092: }
1093: }
1094: }
1095: }
1096: }
1097: }
1098: // second optimization
1099: else if (defs.size() == 2) {
1100:
1101: Unit def0 = defs.get(0);
1102: Unit def1 = defs.get(1);
1103:
1104: Block defBlock0 = mUnitToBlockMap.get(def0);
1105: Block defBlock1 = mUnitToBlockMap.get(def1);
1106: if (defBlock0 != loadBlock
1107: && defBlock1 != loadBlock
1108: && defBlock0 != defBlock1
1109: && !(isExceptionHandlerBlock(loadBlock))) {
1110: if (mLocalUses.getUsesOf(def0).size() == 1
1111: && mLocalUses.getUsesOf(def1)
1112: .size() == 1) {
1113: List def0Succs = defBlock0
1114: .getSuccs();
1115: List def1Succs = defBlock1
1116: .getSuccs();
1117: if (def0Succs.size() == 1
1118: && def1Succs.size() == 1) {
1119: if (def0Succs.get(0) == loadBlock
1120: && def1Succs.get(0) == loadBlock) {
1121: if (loadBlock.getPreds()
1122: .size() == 2) {
1123: if ((def0 == defBlock0
1124: .getTail() || getDeltaStackHeightFromTo(
1125: defBlock0
1126: .getSuccOf(def0),
1127: defBlock0
1128: .getTail()) == 0)
1129: && (def1 == defBlock1
1130: .getTail() || getDeltaStackHeightFromTo(
1131: defBlock1
1132: .getSuccOf(def1),
1133: defBlock1
1134: .getTail()) == 0)) {
1135: defBlock0
1136: .remove(def0);
1137: defBlock1
1138: .remove(def1);
1139: loadBlock
1140: .insertBefore(
1141: def0,
1142: loadBlock
1143: .getHead());
1144: mUnitToBlockMap
1145: .put(def0,
1146: loadBlock);
1147: hasChanged = true;
1148: if (debug) {
1149: G.v().out
1150: .println("inter-block opti2 occurred "
1151: + def0);
1152: }
1153: } else {
1154: if (debug) {
1155: G.v().out
1156: .println("failed: inter1");
1157: }
1158: }
1159: } else {
1160: if (debug) {
1161: G.v().out
1162: .println("failed: inter2");
1163: }
1164: }
1165: } else {
1166: if (debug) {
1167: G.v().out
1168: .println("failed: inter3");
1169: }
1170: }
1171: } else {
1172: if (debug) {
1173: G.v().out
1174: .println("failed: inter4");
1175: }
1176: }
1177: } else {
1178: if (debug) {
1179: G.v().out
1180: .println("failed: inter5");
1181: }
1182: }
1183: } else {
1184: if (debug) {
1185: G.v().out.println("failed: inter6");
1186: }
1187: }
1188: }
1189: }
1190: }
1191: }
1192: }
1193:
1194: /**
1195: * Given 2 blocks, assertains whether all the succesors of the first block are the predecessors
1196: * of the second block.
1197: */
1198: private boolean allSuccesorsOfAreThePredecessorsOf(
1199: Block aFirstBlock, Block aSecondBlock) {
1200: int size = aFirstBlock.getSuccs().size();
1201: Iterator it = aFirstBlock.getSuccs().iterator();
1202:
1203: List preds = aSecondBlock.getPreds();
1204: while (it.hasNext()) {
1205: if (!preds.contains(it.next()))
1206: return false;
1207: }
1208:
1209: if (size == preds.size())
1210: return true;
1211: else
1212: return false;
1213: }
1214:
1215: /**
1216: * @return true if aUnit is a commutative binary operator
1217: */
1218: private boolean isCommutativeBinOp(Unit aUnit) {
1219: if (aUnit == null)
1220: return false;
1221:
1222: if (aUnit instanceof AddInst || aUnit instanceof MulInst
1223: || aUnit instanceof AndInst
1224: || aUnit instanceof OrInst
1225: || aUnit instanceof XorInst)
1226: return true;
1227: else
1228: return false;
1229: }
1230:
1231: void propagateBackwardsIndependentHunk() {
1232:
1233: List<Unit> tempList = new ArrayList<Unit>();
1234: tempList.addAll(mUnits);
1235: Iterator<Unit> it = tempList.iterator();
1236:
1237: while (it.hasNext()) {
1238: Unit u = it.next();
1239:
1240: if (u instanceof NewInst) {
1241: Block block = mUnitToBlockMap.get(u);
1242: Unit succ = block.getSuccOf(u);
1243: if (succ instanceof StoreInst) {
1244: Unit currentUnit = u;
1245: Unit candidate = null;
1246:
1247: while (currentUnit != block.getHead()) {
1248: currentUnit = block.getPredOf(currentUnit);
1249: if (canMoveUnitOver(currentUnit, succ)) {
1250: candidate = currentUnit;
1251: } else
1252: break;
1253: }
1254: if (candidate != null) {
1255: block.remove(u);
1256: block.remove(succ);
1257: block.insertBefore(u, candidate);
1258: block.insertBefore(succ, candidate);
1259: }
1260: }
1261: }
1262: }
1263: }
1264:
1265: // recycled code:
1266: /*
1267: // convertsa series of loads into dups when applicable
1268: void superDuper1() {
1269: List tempList = new ArrayList();
1270: tempList.addAll(mUnits);
1271: Iterator it = tempList.iterator();
1272: boolean fetchUnit = true;
1273:
1274: while(it.hasNext()) {
1275: Unit currentInst = null;
1276:
1277: if(fetchUnit) {
1278: currentInst = (Unit) it.next();
1279: }
1280: fetchUnit = true;
1281:
1282: if(currentInst instanceof LoadInst) {
1283: Block block = (Block) mUnitToBlockMap.get(currentInst);
1284:
1285: Local local = ((LoadInst)currentInst).getLocal();
1286:
1287: // count the number of identical loads
1288:
1289: Unit u;
1290: for(;;){
1291: if(it.hasNext()) {
1292: u = (Unit) it.next();
1293: if(mUnitToBlockMap.get(u) != block)
1294: break;
1295:
1296: if(u instanceof LoadInst) {
1297: if(((LoadInst)u).getLocal() == local) {
1298: replaceUnit(u, Baf.v().newDup1Inst(((LoadInst) u).getOpType()));
1299:
1300: } else {
1301: fetchUnit =false;
1302: break;
1303: }
1304: } else {
1305: break;
1306: }
1307: } else
1308: break;
1309: }
1310: }
1311: }
1312: }
1313:
1314:
1315: //broken use superDuper1
1316: void superDuper() {
1317: // compress a serie of loads using dup2's and dup's
1318: {
1319: List tempList = new ArrayList();
1320: tempList.addAll(mUnits);
1321: Iterator it = tempList.iterator();
1322: while(it.hasNext()) {
1323: Unit currentInst = (Unit) it.next();
1324:
1325: if(currentInst instanceof LoadInst) {
1326: Block block = (Block) mUnitToBlockMap.get(currentInst);
1327:
1328: int loadCount = 1;
1329: Local local = ((LoadInst)currentInst).getLocal();
1330:
1331: // count the number of identical loads
1332:
1333: Unit u;
1334: for(;;){
1335: u = (Unit) it.next();
1336: if(mUnitToBlockMap.get(u) != block)
1337: break;
1338:
1339: if(u instanceof LoadInst) {
1340: if(((LoadInst)u).getLocal() == local)
1341: loadCount++;
1342: else
1343: break;
1344: } else {
1345: break;
1346: }
1347: }
1348:
1349:
1350: if(loadCount > 1) {
1351: Type loadType = ((LoadInst)currentInst).getOpType();
1352:
1353: // must leave at least one load on stack before dupping
1354: Unit currentLoad = (Unit) mUnits.getSuccOf(currentInst);
1355: loadCount--;
1356:
1357: if(loadType instanceof LongType || loadType instanceof DoubleType) {
1358:
1359:
1360:
1361: while(loadCount > 0) {
1362: Unit nextLoad = (Unit) mUnits.getSuccOf(currentLoad);
1363: replaceUnit(currentLoad, Baf.v().newDup1Inst(loadType));
1364:
1365: currentLoad = nextLoad;
1366: loadCount--;
1367: }
1368: } else {
1369: boolean canMakeDup2 = false;
1370: if(loadCount >= 3) {
1371: canMakeDup2 = true;
1372: currentLoad = (Unit) mUnits.getSuccOf(currentLoad);
1373: loadCount--;
1374: }
1375:
1376: while(loadCount > 0) {
1377:
1378: if(loadCount == 1 || !canMakeDup2) {
1379: Unit nextLoad = (Unit) mUnits.getSuccOf(currentLoad);
1380: replaceUnit(currentLoad, Baf.v().newDup1Inst(loadType));
1381:
1382: currentLoad = nextLoad;
1383: loadCount--;
1384: } else {
1385: if(canMakeDup2) {
1386: Unit nextLoad = (Unit) mUnits.getSuccOf(mUnits.getSuccOf(currentLoad));
1387: replaceUnit(currentLoad, (Unit) mUnits.getSuccOf(currentLoad), Baf.v().newDup2Inst(loadType, loadType));
1388: currentLoad = nextLoad;
1389: loadCount -= 2;
1390: }
1391: }
1392: }
1393: }
1394: }
1395: currentInst = u;
1396: }
1397: }
1398: }
1399: }
1400:
1401: void peephole() {
1402: boolean hasChanged = true;
1403:
1404: while(hasChanged) {
1405: hasChanged = false;
1406: List tempList = new ArrayList();
1407: tempList.addAll(mUnits);
1408:
1409: Iterator it = tempList.iterator();
1410: while(it.hasNext() ) {
1411: Unit currentUnit = (Unit) it.next();
1412: if(currentUnit instanceof PopInst) {
1413: Block popBlock = (Block) mUnitToBlockMap.get(currentUnit);
1414: Unit prev = (Unit) popBlock.getPredOf(currentUnit);
1415: Unit succ = (Unit) popBlock.getSuccOf(currentUnit);
1416:
1417: if(prev instanceof LoadInst || prev instanceof PushInst)
1418: if(((AbstractInst)prev).getOutMachineCount() == ((AbstractInst)currentUnit).getInMachineCount()) {
1419: popBlock.remove(prev);
1420: popBlock.remove(currentUnit);
1421: }
1422: else if(succ instanceof ReturnInst) {
1423: popBlock.remove(currentUnit);
1424: popBlock.remove(succ);
1425: }
1426: }
1427: }
1428: }
1429: }
1430:
1431:
1432: private boolean propagateStoreForward(Unit aInst, Unit aUnitToReach, Unit aCurrentUnit, int aStackHeight)
1433: {
1434: boolean res = false;
1435: Unit currentUnit = aCurrentUnit;
1436: Local storeLocal = ((StoreInst)aInst).getLocal();
1437: Block block = (Block) mUnitToBlockMap.get(aCurrentUnit);
1438:
1439: while( currentUnit != block.getTail()) {
1440: if(currentUnit == aUnitToReach) {
1441: if(aStackHeight == 0)
1442: return true;
1443: else
1444: return false;
1445: }
1446:
1447: if(!canMoveUnitOver(aInst, currentUnit)) {
1448: res = false;
1449: break;
1450: }
1451:
1452: aStackHeight -= ((Inst)currentUnit).getInCount();
1453: if(aStackHeight < 0){
1454: res = false;
1455: break;
1456: }
1457: aStackHeight += ((Inst)currentUnit).getOutCount();
1458:
1459: currentUnit = (Unit) block.getSuccOf(currentUnit);
1460: }
1461:
1462: // if we hit the block boundry
1463: if( currentUnit == block.getTail()) {
1464: Iterator it = block.getSuccessors().iterator();
1465: while(it.hasNext()) {
1466: Block b = (Block) it.next();
1467: if(!propagateStoreForward(aInst, aUnitToReach, b.getHead(), aStackHeight))
1468: return false;
1469: }
1470: res = true;
1471: }
1472: return res;
1473: }
1474:
1475: */
1476:
1477: }
1478:
1479: }
|