com.android.dx.ssa.MoveParamCombiner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of builder Show documentation
Show all versions of builder Show documentation
Library to build Android applications.
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dx.ssa;
import com.android.dx.rop.code.CstInsn;
import com.android.dx.rop.code.LocalItem;
import com.android.dx.rop.code.RegOps;
import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.cst.CstInteger;
import java.util.HashSet;
import java.util.List;
/**
* Combine identical move-param insns, which may result from Ropper's
* handling of synchronized methods.
*/
public class MoveParamCombiner {
/** method to process */
private final SsaMethod ssaMeth;
/**
* Processes a method with this optimization step.
*
* @param ssaMethod method to process
*/
public static void process(SsaMethod ssaMethod) {
new MoveParamCombiner(ssaMethod).run();
}
private MoveParamCombiner(SsaMethod ssaMeth) {
this.ssaMeth = ssaMeth;
}
/**
* Runs this optimization step.
*/
private void run() {
// This will contain the definition specs for each parameter
final RegisterSpec[] paramSpecs
= new RegisterSpec[ssaMeth.getParamWidth()];
// Insns to delete when all done
final HashSet deletedInsns = new HashSet();
ssaMeth.forEachInsn(new SsaInsn.Visitor() {
public void visitMoveInsn (NormalSsaInsn insn) {
}
public void visitPhiInsn (PhiInsn phi) {
}
public void visitNonMoveInsn (NormalSsaInsn insn) {
if (insn.getOpcode().getOpcode() != RegOps.MOVE_PARAM) {
return;
}
int param = getParamIndex(insn);
if (paramSpecs[param] == null) {
paramSpecs[param] = insn.getResult();
} else {
final RegisterSpec specA = paramSpecs[param];
final RegisterSpec specB = insn.getResult();
LocalItem localA = specA.getLocalItem();
LocalItem localB = specB.getLocalItem();
LocalItem newLocal;
/*
* Is there local information to preserve?
*/
if (localA == null) {
newLocal = localB;
} else if (localB == null) {
newLocal = localA;
} else if (localA.equals(localB)) {
newLocal = localA;
} else {
/*
* Oddly, these two identical move-params have distinct
* debug info. We'll just keep them distinct.
*/
return;
}
ssaMeth.getDefinitionForRegister(specA.getReg())
.setResultLocal(newLocal);
/*
* Map all uses of specB to specA
*/
RegisterMapper mapper = new RegisterMapper() {
/** @inheritDoc */
public int getNewRegisterCount() {
return ssaMeth.getRegCount();
}
/** @inheritDoc */
public RegisterSpec map(RegisterSpec registerSpec) {
if (registerSpec.getReg() == specB.getReg()) {
return specA;
}
return registerSpec;
}
};
List uses
= ssaMeth.getUseListForRegister(specB.getReg());
// Use list is modified by mapSourceRegisters
for (int i = uses.size() - 1; i >= 0; i--) {
SsaInsn use = uses.get(i);
use.mapSourceRegisters(mapper);
}
deletedInsns.add(insn);
}
}
});
ssaMeth.deleteInsns(deletedInsns);
}
/**
* Returns the parameter index associated with a move-param insn. Does
* not verify that the insn is a move-param insn.
*
* @param insn {@code non-null;} a move-param insn
* @return {@code >=0;} parameter index
*/
private int getParamIndex(NormalSsaInsn insn) {
CstInsn cstInsn = (CstInsn)(insn.getOriginalRopInsn());
int param = ((CstInteger)cstInsn.getConstant()).getValue();
return param;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy