![JAR search and dependency download from the Maven repository](/logo.png)
com.googlecode.dex2jar.ir.ts.RemoveConstantFromSSA Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle Show documentation
Show all versions of gradle Show documentation
fakeradnroid gradle builder
package com.googlecode.dex2jar.ir.ts;
import java.util.*;
import com.googlecode.dex2jar.ir.IrMethod;
import com.googlecode.dex2jar.ir.expr.Constant;
import com.googlecode.dex2jar.ir.expr.Exprs;
import com.googlecode.dex2jar.ir.expr.Local;
import com.googlecode.dex2jar.ir.expr.Value;
import com.googlecode.dex2jar.ir.stmt.AssignStmt;
import com.googlecode.dex2jar.ir.stmt.LabelStmt;
import com.googlecode.dex2jar.ir.stmt.Stmt;
/**
* 1. Remove constant AssignStmt.
*
*
* a = "123";
* return a;
*
*
* to
*
*
* return "123";
*
*
* 2. Remove Phi if all value are equal
*
*
* a = "123";
* // ...
* b = "123";
* // ...
* c = PHI(a, b);
* return c;
*
*
* to
*
*
* // ...
* return "123";
*
*/
public class RemoveConstantFromSSA extends StatedTransformer {
public static final Comparator LOCAL_COMPARATOR = new Comparator() {
@Override
public int compare(Local local, Local t1) {
return Integer.compare(local._ls_index, t1._ls_index);
}
};
@Override
public boolean transformReportChanged(IrMethod method) {
boolean changed = false;
List assignStmtList = new ArrayList<>();
Map cstMap = new HashMap<>();
for (Stmt p = method.stmts.getFirst(); p != null; p = p.getNext()) {
if (p.st == Stmt.ST.ASSIGN) {
AssignStmt as = (AssignStmt) p;
if (as.getOp1().vt == Value.VT.LOCAL) {
if (as.getOp2().vt == Value.VT.CONSTANT) {
assignStmtList.add(as);
cstMap.put((Local) as.getOp1(), ((Constant) as.getOp2()).value);
} else if (as.getOp2().vt == Value.VT.LOCAL) {
cstMap.put((Local) as.getOp1(), as.getOp2());
}
}
}
}
if (assignStmtList.size() == 0) {
return false;
}
RemoveLocalFromSSA.fixReplace(cstMap);
final Map toReplace = new HashMap<>();
Set usedInPhi = new HashSet<>();
List phiLabels = method.phiLabels;
if (phiLabels != null) {
boolean loopAgain = true;
while (loopAgain) {
loopAgain = false;
usedInPhi.clear();
for (Iterator it = phiLabels.iterator(); it.hasNext();) {
LabelStmt labelStmt = it.next();
if (labelStmt.phis != null) {
for (Iterator it2 = labelStmt.phis.iterator(); it2.hasNext();) {
AssignStmt phi = it2.next();
Value[] vs = phi.getOp2().getOps();
Object sameCst = null;
boolean allEqual = true;
for (Value p : vs) {
Object cst = cstMap.get(p);
if (cst == null) {
allEqual = false;
break;
}
if (sameCst == null) {
sameCst = cst;
} else if (!sameCst.equals(cst)) {
allEqual = false;
break;
}
}
if (allEqual) { // all are same constant
cstMap.put((Local) phi.getOp1(), sameCst);
if (sameCst instanceof Local) {
phi.setOp2((Value) sameCst);
} else {
phi.setOp2(Exprs.nConstant(sameCst));
assignStmtList.add(phi);
}
it2.remove();
method.stmts.insertAfter(labelStmt, phi);
changed = true;
loopAgain = true; // loop again
} else {
usedInPhi.addAll(Arrays.asList(phi.getOp2().getOps()));
}
}
if (labelStmt.phis.size() == 0) {
it.remove();
}
}
}
}
}
for (Iterator it = assignStmtList.iterator(); it.hasNext();) {
AssignStmt as = it.next();
if (!usedInPhi.contains(as.getOp1())) {
it.remove();
method.stmts.remove(as);
method.locals.remove(as.getOp1());
changed = true;
}
toReplace.put((Local) as.getOp1(), as.getOp2());
}
Cfg.travelMod(method.stmts, new Cfg.TravelCallBack() {
@Override
public Value onAssign(Local v, AssignStmt as) {
return v;
}
@Override
public Value onUse(Local v) {
Value n = toReplace.get(v);
return n == null ? v : n.clone();
}
}, false);
return changed;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy