use of soot.jimple.toolkits.pointer.PASideEffectTester in project soot by Sable.
the class BusyCodeMotion method internalTransform.
/**
* performs the busy code motion.
*/
protected void internalTransform(Body b, String phaseName, Map<String, String> opts) {
BCMOptions options = new BCMOptions(opts);
HashMap<EquivalentValue, Local> expToHelper = new HashMap<EquivalentValue, Local>();
Chain<Unit> unitChain = b.getUnits();
if (Options.v().verbose())
logger.debug("[" + b.getMethod().getName() + "] performing Busy Code Motion...");
CriticalEdgeRemover.v().transform(b, phaseName + ".cer");
UnitGraph graph = new BriefUnitGraph(b);
/* map each unit to its RHS. only take binary expressions */
Map<Unit, EquivalentValue> unitToEquivRhs = new UnitMap<EquivalentValue>(b, graph.size() + 1, 0.7f) {
protected EquivalentValue mapTo(Unit unit) {
Value tmp = SootFilter.noInvokeRhs(unit);
Value tmp2 = SootFilter.binop(tmp);
if (tmp2 == null)
tmp2 = SootFilter.concreteRef(tmp);
return SootFilter.equiVal(tmp2);
}
};
/* same as before, but without exception-throwing expressions */
Map<Unit, EquivalentValue> unitToNoExceptionEquivRhs = new UnitMap<EquivalentValue>(b, graph.size() + 1, 0.7f) {
protected EquivalentValue mapTo(Unit unit) {
Value tmp = SootFilter.binopRhs(unit);
tmp = SootFilter.noExceptionThrowing(tmp);
return SootFilter.equiVal(tmp);
}
};
/* if a more precise sideeffect-tester comes out, please change it here! */
SideEffectTester sideEffect;
if (Scene.v().hasCallGraph() && !options.naive_side_effect()) {
sideEffect = new PASideEffectTester();
} else {
sideEffect = new NaiveSideEffectTester();
}
sideEffect.newMethod(b.getMethod());
UpSafetyAnalysis upSafe = new UpSafetyAnalysis(graph, unitToEquivRhs, sideEffect);
DownSafetyAnalysis downSafe = new DownSafetyAnalysis(graph, unitToNoExceptionEquivRhs, sideEffect);
EarliestnessComputation earliest = new EarliestnessComputation(graph, upSafe, downSafe, sideEffect);
LocalCreation localCreation = new LocalCreation(b.getLocals(), PREFIX);
Iterator<Unit> unitIt = unitChain.snapshotIterator();
{
/* insert the computations at the earliest positions */
while (unitIt.hasNext()) {
Unit currentUnit = unitIt.next();
for (EquivalentValue equiVal : earliest.getFlowBefore(currentUnit)) {
// Value exp = equiVal.getValue();
/* get the unic helper-name for this expression */
Local helper = expToHelper.get(equiVal);
// the beginning of the method
if (currentUnit instanceof IdentityStmt)
currentUnit = getFirstNonIdentityStmt(b);
if (helper == null) {
helper = localCreation.newLocal(equiVal.getType());
expToHelper.put(equiVal, helper);
}
/* insert a new Assignment-stmt before the currentUnit */
Value insertValue = Jimple.cloneIfNecessary(equiVal.getValue());
Unit firstComp = Jimple.v().newAssignStmt(helper, insertValue);
unitChain.insertBefore(firstComp, currentUnit);
}
}
}
{
/* replace old computations by the helper-vars */
unitIt = unitChain.iterator();
while (unitIt.hasNext()) {
Unit currentUnit = unitIt.next();
EquivalentValue rhs = unitToEquivRhs.get(currentUnit);
if (rhs != null) {
Local helper = expToHelper.get(rhs);
if (helper != null)
((AssignStmt) currentUnit).setRightOp(helper);
}
}
}
if (Options.v().verbose())
logger.debug("[" + b.getMethod().getName() + "] Busy Code Motion done!");
}
use of soot.jimple.toolkits.pointer.PASideEffectTester in project soot by Sable.
the class CommonSubexpressionEliminator method internalTransform.
/**
* Common subexpression eliminator.
*/
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
int counter = 0;
// Sigh. check for name collisions.
Iterator<Local> localsIt = b.getLocals().iterator();
Set<String> localNames = new HashSet<String>(b.getLocals().size());
while (localsIt.hasNext()) {
localNames.add((localsIt.next()).getName());
}
SideEffectTester sideEffect;
if (Scene.v().hasCallGraph() && !PhaseOptions.getBoolean(options, "naive-side-effect")) {
sideEffect = new PASideEffectTester();
} else {
sideEffect = new NaiveSideEffectTester();
}
sideEffect.newMethod(b.getMethod());
if (Options.v().verbose())
logger.debug("[" + b.getMethod().getName() + "] Eliminating common subexpressions " + (sideEffect instanceof NaiveSideEffectTester ? "(naively)" : "") + "...");
// new SlowAvailableExpressions(b);
AvailableExpressions ae = new FastAvailableExpressions(b, sideEffect);
Chain<Unit> units = b.getUnits();
Iterator<Unit> unitsIt = units.snapshotIterator();
while (unitsIt.hasNext()) {
Stmt s = (Stmt) unitsIt.next();
if (s instanceof AssignStmt) {
Chain availExprs = ae.getAvailableEquivsBefore(s);
// logger.debug("availExprs: "+availExprs);
Value v = ((AssignStmt) s).getRightOp();
EquivalentValue ev = new EquivalentValue(v);
if (availExprs.contains(ev)) {
// now we need to track down the containing stmt.
List availPairs = ae.getAvailablePairsBefore(s);
// logger.debug("availPairs: "+availPairs);
Iterator availIt = availPairs.iterator();
while (availIt.hasNext()) {
UnitValueBoxPair up = (UnitValueBoxPair) availIt.next();
if (up.getValueBox().getValue().equivTo(v)) {
// create a local for temp storage.
// (we could check to see that the def must-reach, I guess...)
String newName = "$cseTmp" + counter;
counter++;
while (localNames.contains(newName)) {
newName = "$cseTmp" + counter;
counter++;
}
Local l = Jimple.v().newLocal(newName, Type.toMachineType(v.getType()));
b.getLocals().add(l);
// I hope it's always an AssignStmt -- Jimple should guarantee this.
AssignStmt origCalc = (AssignStmt) up.getUnit();
Value origLHS = origCalc.getLeftOp();
origCalc.setLeftOp(l);
Unit copier = Jimple.v().newAssignStmt(origLHS, l);
units.insertAfter(copier, origCalc);
((AssignStmt) s).setRightOp(l);
copier.addTag(new StringTag("Common sub-expression"));
s.addTag(new StringTag("Common sub-expression"));
// logger.debug("added tag to : "+copier);
// logger.debug("added tag to : "+s);
}
}
}
}
}
if (Options.v().verbose())
logger.debug("[" + b.getMethod().getName() + "] Eliminating common subexpressions done!");
}
use of soot.jimple.toolkits.pointer.PASideEffectTester in project soot by Sable.
the class LazyCodeMotion method internalTransform.
/**
* performs the lazy code motion.
*/
protected void internalTransform(Body b, String phaseName, Map<String, String> opts) {
LCMOptions options = new LCMOptions(opts);
HashMap<EquivalentValue, Local> expToHelper = new HashMap<EquivalentValue, Local>();
Chain<Unit> unitChain = b.getUnits();
if (Options.v().verbose())
logger.debug("[" + b.getMethod().getName() + "] Performing Lazy Code Motion...");
if (options.unroll())
new LoopConditionUnroller().transform(b, phaseName + ".lcu");
CriticalEdgeRemover.v().transform(b, phaseName + ".cer");
UnitGraph graph = new BriefUnitGraph(b);
/* map each unit to its RHS. only take binary expressions */
Map<Unit, EquivalentValue> unitToEquivRhs = new UnitMap<EquivalentValue>(b, graph.size() + 1, 0.7f) {
protected EquivalentValue mapTo(Unit unit) {
Value tmp = SootFilter.noInvokeRhs(unit);
Value tmp2 = SootFilter.binop(tmp);
if (tmp2 == null)
tmp2 = SootFilter.concreteRef(tmp);
return SootFilter.equiVal(tmp2);
}
};
/* same as before, but without exception-throwing expressions */
Map<Unit, EquivalentValue> unitToNoExceptionEquivRhs = new UnitMap<EquivalentValue>(b, graph.size() + 1, 0.7f) {
protected EquivalentValue mapTo(Unit unit) {
Value tmp = SootFilter.binopRhs(unit);
tmp = SootFilter.noExceptionThrowing(tmp);
return SootFilter.equiVal(tmp);
}
};
FlowUniverse<EquivalentValue> universe = new CollectionFlowUniverse<EquivalentValue>(unitToEquivRhs.values());
BoundedFlowSet<EquivalentValue> set = new ArrayPackedSet<EquivalentValue>(universe);
/* if a more precise sideeffect-tester comes out, please change it here! */
SideEffectTester sideEffect;
if (Scene.v().hasCallGraph() && !options.naive_side_effect()) {
sideEffect = new PASideEffectTester();
} else {
sideEffect = new NaiveSideEffectTester();
}
sideEffect.newMethod(b.getMethod());
UpSafetyAnalysis upSafe;
DownSafetyAnalysis downSafe;
EarliestnessComputation earliest;
DelayabilityAnalysis delay;
NotIsolatedAnalysis notIsolated;
LatestComputation latest;
if (options.safety() == LCMOptions.safety_safe)
upSafe = new UpSafetyAnalysis(graph, unitToNoExceptionEquivRhs, sideEffect, set);
else
upSafe = new UpSafetyAnalysis(graph, unitToEquivRhs, sideEffect, set);
if (options.safety() == LCMOptions.safety_unsafe)
downSafe = new DownSafetyAnalysis(graph, unitToEquivRhs, sideEffect, set);
else {
downSafe = new DownSafetyAnalysis(graph, unitToNoExceptionEquivRhs, sideEffect, set);
/* we include the exception-throwing expressions at their uses */
Iterator<Unit> unitIt = unitChain.iterator();
while (unitIt.hasNext()) {
Unit currentUnit = unitIt.next();
EquivalentValue rhs = unitToEquivRhs.get(currentUnit);
if (rhs != null)
downSafe.getFlowBefore(currentUnit).add(rhs);
}
}
earliest = new EarliestnessComputation(graph, upSafe, downSafe, sideEffect, set);
delay = new DelayabilityAnalysis(graph, earliest, unitToEquivRhs, set);
latest = new LatestComputation(graph, delay, unitToEquivRhs, set);
notIsolated = new NotIsolatedAnalysis(graph, latest, unitToEquivRhs, set);
LocalCreation localCreation = new LocalCreation(b.getLocals(), PREFIX);
/* debug */
/*
* { logger.debug("========" + b.getMethod().getName()); Iterator
* unitIt = unitChain.iterator(); while (unitIt.hasNext()) { Unit
* currentUnit = (Unit) unitIt.next(); Value equiVal =
* (Value)unitToEquivRhs.get(currentUnit); FlowSet latestSet =
* (FlowSet)latest.getFlowBefore(currentUnit); FlowSet notIsolatedSet =
* (FlowSet)notIsolated.getFlowAfter(currentUnit); FlowSet delaySet =
* (FlowSet)delay.getFlowBefore(currentUnit); FlowSet earlySet =
* ((FlowSet)earliest.getFlowBefore(currentUnit)); FlowSet upSet =
* (FlowSet)upSafe.getFlowBefore(currentUnit); FlowSet downSet =
* (FlowSet)downSafe.getFlowBefore(currentUnit);
* logger.debug(""+currentUnit); logger.debug(" rh: " + equiVal);
* logger.debug(" up: " + upSet); logger.debug(" do: " +
* downSet); logger.debug(" is: " + notIsolatedSet);
* logger.debug(" ea: " + earlySet); logger.debug(" db: " +
* delaySet); logger.debug(" la: " + latestSet); } }
*/
{
/* insert the computations */
for (Iterator<Unit> unitIt = unitChain.snapshotIterator(); unitIt.hasNext(); ) {
Unit currentUnit = unitIt.next();
FlowSet<EquivalentValue> latestSet = latest.getFlowBefore(currentUnit);
FlowSet<EquivalentValue> notIsolatedSet = notIsolated.getFlowAfter(currentUnit);
FlowSet<EquivalentValue> insertHere = latestSet.clone();
insertHere.intersection(notIsolatedSet, insertHere);
for (EquivalentValue equiVal : insertHere) {
/* get the unic helper-name for this expression */
Local helper = expToHelper.get(equiVal);
if (helper == null) {
helper = localCreation.newLocal(equiVal.getType());
expToHelper.put(equiVal, helper);
}
/* insert a new Assignment-stmt before the currentUnit */
Value insertValue = Jimple.cloneIfNecessary(equiVal.getValue());
Unit firstComp = Jimple.v().newAssignStmt(helper, insertValue);
unitChain.insertBefore(firstComp, currentUnit);
}
}
}
{
/* replace old computations by the helper-vars */
Iterator<Unit> unitIt = unitChain.iterator();
while (unitIt.hasNext()) {
Unit currentUnit = (Unit) unitIt.next();
EquivalentValue rhs = (EquivalentValue) unitToEquivRhs.get(currentUnit);
if (rhs != null) {
FlowSet<EquivalentValue> latestSet = latest.getFlowBefore(currentUnit);
FlowSet<EquivalentValue> notIsolatedSet = notIsolated.getFlowAfter(currentUnit);
if (!latestSet.contains(rhs) && notIsolatedSet.contains(rhs)) {
Local helper = expToHelper.get(rhs);
try {
if (helper != null)
((AssignStmt) currentUnit).setRightOp(helper);
} catch (RuntimeException e) {
logger.debug("Error on " + b.getMethod().getName());
logger.debug("" + currentUnit.toString());
logger.debug("" + latestSet);
logger.debug("" + notIsolatedSet);
throw e;
}
}
}
}
}
if (Options.v().verbose())
logger.debug("[" + b.getMethod().getName() + "] Lazy Code Motion done.");
}
Aggregations