Replace simple if condition swapping heuristic with a smarter one

This allows us to change expressions like `!a && !b` to `a || b`. It
isn't perfect, as we will now flip bitwise flag checks (which was one of
the main motivations for the old heuristic).
bzip2
Graham 5 years ago
parent e202c4fcb9
commit f742aba80d
  1. 8
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.java
  2. 16
      deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.java

@ -54,11 +54,11 @@ public final class IfElseTransformer extends Transformer {
} }
/* /*
* Prefer if (a) over if (!a). We don't swap != as it makes * Prefer fewer NOTs in the if condition.
* checking bitwise flags look worse.
*/ */
if (ExprUtils.isNot(condition)) { var notCondition = ExprUtils.not(condition);
stmt.setCondition(ExprUtils.not(condition)); if (ExprUtils.countNots(notCondition) < ExprUtils.countNots(condition)) {
stmt.setCondition(notCondition);
stmt.setThenStmt(elseStmt.clone()); stmt.setThenStmt(elseStmt.clone());
stmt.setElseStmt(thenStmt.clone()); stmt.setElseStmt(thenStmt.clone());
} }

@ -71,6 +71,22 @@ public final class ExprUtils {
return new UnaryExpr(expr.clone(), UnaryExpr.Operator.LOGICAL_COMPLEMENT); return new UnaryExpr(expr.clone(), UnaryExpr.Operator.LOGICAL_COMPLEMENT);
} }
public static int countNots(Expression expr) {
int count = 0;
if (expr.isUnaryExpr() && expr.asUnaryExpr().getOperator() == UnaryExpr.Operator.LOGICAL_COMPLEMENT) {
count++;
} else if (expr.isBinaryExpr() && expr.asBinaryExpr().getOperator() == BinaryExpr.Operator.NOT_EQUALS) {
count++;
}
for (Expression child : expr.getChildNodesByType(Expression.class)) {
count += countNots(child);
}
return count;
}
public static boolean hasSideEffects(Expression expr) { public static boolean hasSideEffects(Expression expr) {
if (expr.isLiteralExpr() || expr.isNameExpr() | expr.isFieldAccessExpr()) { if (expr.isLiteralExpr() || expr.isNameExpr() | expr.isFieldAccessExpr()) {
return false; return false;

Loading…
Cancel
Save