Skip to content

Commit

Permalink
fix: inline CMP instructions to help conditions merge (#2033)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Oct 21, 2023
1 parent 4a92ee0 commit b310e92
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 2 deletions.
28 changes: 28 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package jadx.core.dex.visitors;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -58,6 +59,7 @@
import jadx.core.utils.exceptions.JadxRuntimeException;

import static jadx.core.utils.BlockUtils.replaceInsn;
import static jadx.core.utils.ListUtils.allMatch;

/**
* Visitor for modify method instructions
Expand Down Expand Up @@ -139,6 +141,11 @@ private static void replaceStep(MethodNode mth, InsnRemover remover) {
processArith(mth, parentClass, (ArithNode) insn);
break;

case CMP_L:
case CMP_G:
inlineCMPInsns(mth, block, i, insn, remover);
break;

case CHECK_CAST:
removeCheckCast(mth, block, i, (IndexInsnNode) insn);
break;
Expand Down Expand Up @@ -348,6 +355,27 @@ private static void processArith(MethodNode mth, ClassNode parentClass, ArithNod
}
}

/**
* Inline CMP instructions into 'if' to help conditions merging
*/
private static void inlineCMPInsns(MethodNode mth, BlockNode block, int i, InsnNode insn, InsnRemover remover) {
RegisterArg resArg = insn.getResult();
List<RegisterArg> useList = resArg.getSVar().getUseList();
if (allMatch(useList, use -> InsnUtils.isInsnType(use.getParentInsn(), InsnType.IF))) {
for (RegisterArg useArg : new ArrayList<>(useList)) {
InsnNode useInsn = useArg.getParentInsn();
if (useInsn != null) {
InsnArg wrapArg = InsnArg.wrapInsnIntoArg(insn.copyWithoutResult());
if (!useInsn.replaceArg(useArg, wrapArg)) {
mth.addWarnComment("Failed to inline CMP insn: " + insn + " into " + useInsn);
return;
}
}
}
remover.addAndUnbind(insn);
}
}

private static boolean checkArrSizes(MethodNode mth, NewArrayNode newArrInsn, FillArrayInsn fillArrInsn) {
int dataSize = fillArrInsn.getSize();
InsnArg arrSizeArg = newArrInsn.getArg(0);
Expand Down
7 changes: 5 additions & 2 deletions jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jadx.core.Consts;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.IAttributeNode;
import jadx.core.dex.attributes.nodes.JadxError;
Expand All @@ -19,7 +20,7 @@

public class ErrorsCounter {
private static final Logger LOG = LoggerFactory.getLogger(ErrorsCounter.class);
private static final boolean PRINT_MTH_SIZE = true;
private static final boolean PRINT_MTH_SIZE = Consts.DEBUG;

private final Set<IAttributeNode> errorNodes = new HashSet<>();
private int errorsCount;
Expand All @@ -44,7 +45,9 @@ private synchronized <N extends IDexNode & IAttributeNode> String addError(N nod

String msg = formatMsg(node, error);
if (PRINT_MTH_SIZE && node instanceof MethodNode) {
msg = "[" + ((MethodNode) node).getInsnsCount() + "] " + msg;
String mthSize = "[" + ((MethodNode) node).getInsnsCount() + "] ";
msg = mthSize + msg;
error = mthSize + error;
}
if (e == null) {
LOG.error(msg);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package jadx.tests.integration.conditions;

import org.junit.jupiter.api.Test;

import jadx.tests.api.SmaliTest;

public class TestTernaryInIf3 extends SmaliTest {

@Test
public void test() {
disableCompilation();
getClassNodeFromSmali();
}
}
157 changes: 157 additions & 0 deletions jadx-core/src/test/smali/conditions/TestTernaryInIf3.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
.class public Lconditions/TestTernaryInIf3;
.super Ljava/lang/Object;

.method public static final A01(LX/73h;FFZ)Landroid/util/Pair;
.registers 7

.line 0
const/4 v1, 0x0

.line 1
cmpl-float v0, p1, v1

.line 2
.line 3
if-eqz v0, :cond_33

.line 4
.line 5
cmpl-float v0, p2, v1

.line 6
.line 7
if-eqz v0, :cond_33

.line 8
.line 9
if-eqz p3, :cond_24

.line 10
.line 11
cmpg-float v0, p2, v1

.line 12
.line 13
if-ltz v0, :cond_26

.line 14
.line 15
:cond_f
iget-object v1, p0, LX/73h;->A00:LX/5Yj;

.line 16
.line 17
const-string v0, "translationXCurveDownwards"

.line 18
.line 19
invoke-virtual {v1, v0}, LX/5Yj;->A03(Ljava/lang/String;)LX/5Wd;

.line 20
.line 21
.line 22
move-result-object v2

.line 23
iget-object v1, p0, LX/73h;->A00:LX/5Yj;

.line 24
.line 25
const-string v0, "translationYCurveDownwards"

.line 26
.line 27
:goto_1b
invoke-virtual {v1, v0}, LX/5Yj;->A03(Ljava/lang/String;)LX/5Wd;

.line 28
.line 29
.line 30
move-result-object v0

.line 31
invoke-static {v2, v0}, LX/0xz;->A0F(Ljava/lang/Object;Ljava/lang/Object;)Landroid/util/Pair;

.line 32
.line 33
.line 34
move-result-object v0

.line 35
return-object v0

.line 36
:cond_24
if-lez v0, :cond_f

.line 37
.line 38
:cond_26
iget-object v1, p0, LX/73h;->A00:LX/5Yj;

.line 39
.line 40
const-string v0, "translationXCurveUpwards"

.line 41
.line 42
invoke-virtual {v1, v0}, LX/5Yj;->A03(Ljava/lang/String;)LX/5Wd;

.line 43
.line 44
.line 45
move-result-object v2

.line 46
iget-object v1, p0, LX/73h;->A00:LX/5Yj;

.line 47
.line 48
const-string v0, "translationYCurveUpwards"

.line 49
.line 50
goto :goto_1b

.line 51
:cond_33
iget-object v1, p0, LX/73h;->A00:LX/5Yj;

.line 52
.line 53
const-string v0, "translationXLinear"

.line 54
.line 55
invoke-virtual {v1, v0}, LX/5Yj;->A03(Ljava/lang/String;)LX/5Wd;

.line 56
.line 57
.line 58
move-result-object v2

.line 59
iget-object v1, p0, LX/73h;->A00:LX/5Yj;

.line 60
.line 61
const-string v0, "translationYLinear"

.line 62
.line 63
goto :goto_1b
.line 64
.line 65
.line 66
.line 67
.line 68
.line 69
.line 70
.line 71
.line 72
.line 73
.line 74
.line 75
.line 76
.line 77
.end method

0 comments on commit b310e92

Please sign in to comment.