Mirror of the BLOAT repository https://www.cs.purdue.edu/homes/hosking/bloat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
bloat/src/edu/purdue/cs/bloat/trans/Peephole.java

985 lines
39 KiB

/*
* Class: Peephole
* Version:
* Date:
*
* All files in the distribution of BLOAT (Bytecode Level Optimization and
* Analysis tool for Java(tm)) are Copyright 1997-2001 by the Purdue
* Research Foundation of Purdue University. All rights reserved.
*
* <p>
*
* Redistribution and use in source and binary forms are permitted
* provided that this entire copyright notice is duplicated in all
* such copies, and that any documentation, announcements, and other
* materials related to such distribution and use acknowledge that the
* software was developed at Purdue University, West Lafayette, IN by
* @author Antony Hosking
* @author David Whitlock
* @author Nathaniel Nystrom
* No charge may be made for copies, derivations, or distributions of
* this material without the express written consent of the copyright
* holder. Neither the name of the University nor the name of the
* author may be used to endorse or promote products derived from this
* material without specific prior written permission. THIS SOFTWARE
* IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE.
*
* <p>
*
* Port of the BLOAT to use the Jakata Apache project BCEL 5.2 was
* contributed by The Australian National University by
* @author Arrin Daley
* @author John N Zigman
*
* <p>
* Java is a trademark of Sun Microsystems, Inc.
*/
package edu.purdue.cs.bloat.trans;
import org.apache.bcel.generic.*;
import edu.purdue.cs.bloat.cfg.FlowGraph;
import edu.purdue.cs.bloat.optimize.MethodState;
import edu.purdue.cs.bloat.optimize.Optimization;
import edu.purdue.cs.bloat.util.Assert;
import java.util.*;
/**
* Performs some peephole optimizations such as loads and stores and removes
* unreachable instructions.
*/
public class Peephole implements Optimization {
public static boolean DEBUG = false;
public String traceMessage(String dateString) {
return null;
}
public String preDebugMessage() {
return null;
}
public String postDebugMessage() {
return null;
}
public void transform(MethodState state) {
this.transform(state.methodGen(), true);
}
/**
* Perform peephole optimizations on the bytecodes in a method. Peephole
* optimizations look at two consecutive instructions and try to perform
* some simple optimization. For instance, a push followed by a pop is
* uninteresting, so both of those instructions can be removed.
*
* <p>
*
* After the peephole optimizations are performed a final phase removes
* instructions that are not reachable. These instructions reside in basic
* blocks whose starting label is never jumped to.
*/
// Peephole can work on any bytecode sequence it does not have to be a
// result of calls
// to CodeGenerator. However, if Peephole will need to have labels denoting
// the start
// of basic blocks, if the code is not the result of output from
// CodeGenerator then labels
// will not be intact set "labels" to false if this is the case and they can
// be placed using
// FlowGraph.buildBLOATInstructionList(MethodGen) --Arrin
public void transform(MethodGen method, boolean labels) {
if (DEBUG) {
System.out.println("Peephole optimizing " + method);
}
// Map between labels and the instruction that they label
Map targets = new LinkedHashMap();
LinkedList jumps = new LinkedList(); // Jump instructions
Instruction next = null;
InstructionList code = method.getInstructionList();
// Do we need to build the labels are they already intact?
if (!labels)
FlowGraph.buildBLOATInstructionList(method);
InstructionHandle ih = null;
// Go backwards so we can eliminate redundant loads and stores
// in one pass. During the pass collect the locations of labels.
boolean canFilter = true;
CODE: for (ih = code.getEnd(); ih != code.getStart(); ih = ih.getPrev()) {
if (FlowGraph.label(ih)) {
targets.put(ih, ih.getInstruction());
}
// All items are Instructions now
Instruction inst = ih.getInstruction();
Filter peep = null;
// Have we seen a label that starts a block? (i.e. is a target)
boolean seenLabel = false;
if (inst instanceof GotoInstruction) {
// Look at the instructions following the goto. If an
// instruction follows and no label (that starts a block)
// has been seen, the instruction is dead and can be
// removed. If the target of the goto follows the goto
// instruction, the goto is useless and is removed.
InstructionHandle target = ((GotoInstruction) inst).getTarget();
for (InstructionHandle j = ih.getNext(); j != null; j = j
.getNext()) {
// Replace
// goto L
// L: inst
// with
// L: inst
//
if (FlowGraph.label(j)) {
// if (((Label) t).startsBlock()) {
// All labels start a block now
seenLabel = true;
if (target.equals(j)) {
InstructionHandle toDelete = ih;
ih = ih.getNext();
try {
code.delete(toDelete);
next = null;
} catch (TargetLostException tle) {
InstructionHandle[] losttargets = tle
.getTargets();
for (int i = 0; i < losttargets.length; i++) {
InstructionTargeter[] targeters = losttargets[i]
.getTargeters();
for (int k = 0; k < targeters.length; k++)
targeters[k].updateTarget(
losttargets[i], j);
}
// Redirect Lost targeters
}
continue CODE;
}
if (Peephole.DEBUG)
System.out.println("Not a target instruction : "
+ j.getInstruction());
// Now we want to look at the instruction
// continue;
}
// Replace
// goto L
// this is unreachable
// M: inst (M is a different label from L!)
// with
// goto L
// M: inst
//
// if (!FlowGraph.label(j)) {
if (seenLabel) {
break;
}
InstructionHandle j2 = j;
j = j.getPrev();
try {
code.delete(j2); // Delete an unreachable instruction
} catch (TargetLostException tle) {
System.out.println("Got a lost Target!!!!!!!");
// fail quitely
}
// }
}
}
if (inst instanceof GotoInstruction || inst instanceof Select
|| inst instanceof IfInstruction) {
jumps.add(ih);
}
// Performs some peephole optimizations using the filter
// method that returns an instance of the Filter class. The
// filter method looks at two consecutive instructions and
// determines whether or not something about them can be
// changed. For instance, if a push is followed by a pop,
// both instructions are useless and can be eliminated. The
// contents of the Filter object represents the effects of the
// peephole optimization.
if (next != null && canFilter) {
peep = filter(inst, next, method);
}
if (peep != null) {
if (Peephole.DEBUG) {
if (peep.replace.length == 0) {
System.out.println("eliminate " + ih.getInstruction()
+ "-" + ih.getNext().getInstruction());
} else {
System.out.println("replace " + ih.getInstruction()
+ "-" + ih.getNext().getInstruction());
System.out.println(" with");
for (int j = 0; j < peep.replace.length; j++) {
System.out.println(" " + peep.replace[j]);
}
}
}
InstructionHandle oldIh = ih;
ih = ih.getPrev();
InstructionHandle redirectTo = ih.getNext().getNext();
// if no Instruction is added redirect to after the deleted
// instructions
if (ih == null) {// we are at the start of the
// InstructionList
// Add instructions resulting from peephole optimizations
for (int j = peep.replace.length - 1; j >= 0; j--) {
if (peep.replace[j] instanceof BranchInstruction)
redirectTo = code
.insert((BranchInstruction) peep.replace[j]);
else
// UGH BCEL treats Branch instructions differently
redirectTo = code.insert(peep.replace[j]);
// break;
}
} else {
for (int j = peep.replace.length - 1; j >= 0; j--) {
if (peep.replace[j] instanceof BranchInstruction)
redirectTo = code.append(ih,
(BranchInstruction) peep.replace[j]);
else
// UGH BCEL treats Branch instructions differently
redirectTo = code.append(ih, peep.replace[j]);
}
}
try {
// Remove old instructions
code.delete(oldIh.getNext());
code.delete(oldIh);
} catch (TargetLostException tle) {
FlowGraph.setLabel(redirectTo); // reinstate as a label.
InstructionHandle[] losttargets = tle.getTargets();
for (int i = 0; i < losttargets.length; i++) {
InstructionTargeter[] targeters = losttargets[i]
.getTargeters();
for (int j = 0; j < targeters.length; j++)
targeters[j].updateTarget(losttargets[i],
redirectTo);
}
// Redirect Lost targeters
}
ih = ih.getNext();// This should be one of the added
// instructions if one was added.
if (ih != null && !FlowGraph.label(ih)) {
next = ih.getInstruction();
} else {
// No more instructions, or next thing is a label
next = null;
}
} else {
if (ih != null && !FlowGraph.label(ih)) {
next = ih.getInstruction();
} else {
next = null;
}
// Filter didn't find any peephole optimizations, skip to
// next pair of instructions.
}
}
if (DEBUG) {
System.out.println("Peephole optimizing removing GOTOs");
}
// Replace the target of jumps to gotos with the goto target.
// Replace gotos to unconditional jumps with the unconditional jump.
while (!jumps.isEmpty()) {
InstructionHandle iHandle = (InstructionHandle) jumps.removeFirst();
InstructionHandle target;
if ((iHandle.getInstruction() instanceof GotoInstruction)
|| (iHandle.getInstruction() instanceof IfInstruction)) {
BranchInstruction inst = (BranchInstruction) iHandle
.getInstruction();
target = inst.getTarget();
if (target != null) {
Instruction targetInst = target.getInstruction();
if (targetInst instanceof GotoInstruction
&& !(((GotoInstruction) targetInst).getTarget()
.equals(inst.getTarget()))) {
// IF THIS WASN'T TRUE WOULDN'T IT MEAN WE HAVE A GOTO
// DIRECTED TO JUMP TO ITSELF?
if (Peephole.DEBUG) {
System.out.println("replace " + inst);
}
inst.setTarget(((GotoInstruction) targetInst)
.getTarget());
if (Peephole.DEBUG) {
System.out.println(" with " + inst);
}
jumps.add(iHandle);
} else if ((inst instanceof GotoInstruction)
&& (targetInst instanceof Select ||
// targetInst instanceof ReturnInstruction ||
targetInst instanceof ATHROW)) {
if (Peephole.DEBUG) {
System.out.println("replace " + inst);
}
iHandle.setInstruction((BranchInstruction) targetInst
.copy());
// THIS MIGHT BE BAD copy() IS A SHALLOW COPY!!
if (Peephole.DEBUG) {
System.out.println(" with " + targetInst);
}
}
}
}
}
// Remove unreachable code.
removeUnreachable(method, code);
Iterator iterhandles = method.getInstructionList().iterator();
while (iterhandles.hasNext()) {
ih = (InstructionHandle) iterhandles.next();
ih.removeAttribute("Label");
}
method.removeNOPs();
method.getInstructionList().setPositions();
method.setMaxStack();
method.setMaxLocals();
method.update();
if (Peephole.DEBUG) {
System.out.println("END PEEPHOLE--------------------------------");
}
}
/**
* Iterate over the code in the method and determine which labels begin
* blocks that are reachable. The code in blocks that are not reachable is
* removed.
*/
// TODO: Currently, ALL ret targets are marked reachable from a
// single ret. Correct this by looking at the local variables.
private void removeUnreachable(MethodGen method, InstructionList code) {
// Maps Labels to their instruction position
Map labelPos = new LinkedHashMap();
// Collect all the ret targets.
Iterator iter = code.iterator();
int i = 0;
while (iter.hasNext()) {
InstructionHandle ce = (InstructionHandle) iter.next();
if (FlowGraph.label(ce)) {
labelPos.put(ce, new Integer(i));
}
i++;
}
// Visit the blocks depth-first.
// Stack of Labels that begin blocks that have been visited
Set visited = new LinkedHashSet();
// Stack of Labels that begin blocks that have not been visited
Stack stack = new Stack();
InstructionHandle label; // Current label
if (code.getLength() > 0) {
// Start with the label of the first block
label = (InstructionHandle) code.getStart();
visited.add(label);
stack.push(label);
}
CodeExceptionGen[] excptns = method.getExceptionHandlers();
for (i = 0; i < excptns.length; i++) {
// All exception handlers are considered to be live
visited.add(excptns[i].getHandlerPC());
stack.push(excptns[i].getHandlerPC());
}
while (!stack.isEmpty()) {
label = (InstructionHandle) stack.pop();
Integer labelIndex = (Integer) labelPos.get(label);
Assert.isTrue(labelIndex != null, "Index of label_"
+ label.getPosition() + " not found");
InstructionHandle blockIter = label;
while (blockIter != null && blockIter.getNext() != null) {
// Iterate over the code in the block. If we encounter
// instructions that change execution (i.e. go to another
// block), add the Label of the target of the jump to the
// stack if it is not already present.
blockIter = blockIter.getNext();
Instruction inst = blockIter.getInstruction();
// BCEL - BLOAT means jumps can also be Labels.
if (FlowGraph.label(blockIter)) {
label = blockIter;
visited.add(label);
}
if (inst instanceof ReturnInstruction || inst instanceof ATHROW) {
// We've reached the end of the block, but we don't know
// which block will be executed next.
break;
} else if (inst instanceof IfInstruction
|| inst instanceof JsrInstruction) {
// We've reached the end of the block, add the Label of
// the next block to be executed to the list. It's a
// conditional jump, so don't break. The rest of the
// code in the block is not necessarily dead.
label = ((BranchInstruction) inst).getTarget();
if (!visited.contains(label)) {
visited.add(label);
stack.push(label);
}
// Fall through.
} else if (inst instanceof GotoInstruction) {
// Add next block to work list.
label = ((GotoInstruction) inst).getTarget();
if (!visited.contains(label)) {
visited.add(label);
stack.push(label);
}
break;
} else if (inst instanceof RET) {
// The ret targets were handled by the jsr.
break;
} else if (inst instanceof Select) {
// A switch. Add all possible targets of the switch to
// the worklist.
Select sw = (Select) inst;
label = sw.getTarget();
if (!visited.contains(label)) {
visited.add(label);
stack.push(label);
}
InstructionHandle[] targets = sw.getTargets();
for (int j = 0; j < targets.length; j++) {
label = targets[j];
if (!visited.contains(label)) {
visited.add(label);
stack.push(label);
}
}
break;
}
}
}
if (DEBUG) {
System.out.println("Done finding unreachable instructions");
}
boolean reachable = false;
iter = code.iterator();
// Remove unreachable instructions
while (iter.hasNext()) {
InstructionHandle ce = (InstructionHandle) iter.next();
if (FlowGraph.label(ce)) {
reachable = visited.contains(ce);
// Don't remove unreachable labels, only instructions.
}
if (!reachable) {
if (Peephole.DEBUG) {
System.out.println("Removing unreachable " + ce);
}
try {
code.delete(ce);
} catch (TargetLostException lte) {
// do nothing if this is dead code there shouldn't be a
// targeter.
}
}
}
}
/**
* Filter represents a set of instructions that result from a peephole
* optimizations. For instance, when uninteresting instructions are removed,
* a Filter object with an empty "replace" array will be returned by the
* below filter method.
*/
static class Filter {
Instruction[] replace;
boolean[] labels;
Filter() {
this.replace = new Instruction[0];
}
Filter(Instruction replace) {
this.replace = new Instruction[] { replace };
}
Filter(Instruction replace1, Instruction replace2) {
this.replace = new Instruction[] { replace1, replace2 };
}
}
/**
* Filter a pair of instructions. That is, do a peephole optimization on two
* consecutive instructions. For instance, if a push is followed by a pop,
* both instructions can be eliminated. The <tt>Filter</tt> object that is
* returned specifies what instruction(s), if any, should replace the two
* instructions that are the parameters to this method.
*
* @param first
* The first instruction.
* @param second
* The second instruction.
* @return A list of instructions to replace the two instructions with, or
* null, if the instructions should be left as is.
*/
private Filter filter(Instruction first, Instruction second,
MethodGen method) {
// switch (second.opcodeClass()) {
// swap means nothing if it's after a dup.
// (goodbye means nothing when it's all for show
// so stop pretending you've somewhere else to go.)
// case opcx_swap:
if (second instanceof SWAP) {
// Elminate swap-swap
if (first instanceof SWAP)
return new Filter();
// swap means nothing if it's after a dup.
// (goodbye means nothing when it's all for show
// so stop pretending you've somewhere else to go.)
if (first instanceof DUP) {
return new Filter(first);
}
} else if (second instanceof POP) {// Eliminate push-pop.
// Eliminate push-pop.
// switch (first.opcodeClass()) {
if (first instanceof LDC) {
LDC f = (LDC) first;
// Make sure things being popped off is not wide (we're
// dealing with a pop not a pop2).
Assert.isTrue(!(f.getType(method.getConstantPool())
.equals(Type.LONG))
&& !(f.getType(method.getConstantPool())
.equals(Type.DOUBLE)),
"Cannot pop a 2-word operand");
return new Filter();
} else if ((first instanceof ILOAD) || (first instanceof FLOAD)
|| (first instanceof ALOAD) || (first instanceof DUP)) {
// Eliminate the load and the pop.
return new Filter();
} else if (first instanceof DUP_X1) {
// Replace dup_x1-pop with swap
// (As if this is really likely to happen ;) <-- Nate made a
// joke!
System.out.println("HERE0 inserting SWAP");
return new Filter(new SWAP());
}
} else if (second instanceof POP2) {
if (first instanceof LDC) {
LDC f = (LDC) first;
Assert.isTrue((f.getType(method.getConstantPool())
.equals(Type.LONG))
|| (f.getType(method.getConstantPool())
.equals(Type.DOUBLE)),
"Cannot pop2 a 1-word operand");
return new Filter();
} else if ((first instanceof LLOAD) || (first instanceof DLOAD)
|| (first instanceof DUP2)) {
// Eliminate push and pop
return new Filter();
}
} else if (second instanceof ISTORE) {
StoreInstruction secnd = (StoreInstruction) second;
// Eliminate load-store to same location.
if (first instanceof ILOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter();
}
}
} else if (second instanceof FSTORE) {
StoreInstruction secnd = (StoreInstruction) second;
if (first instanceof FLOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter();
}
}
} else if (second instanceof ASTORE) {
StoreInstruction secnd = (StoreInstruction) second;
if (first instanceof ALOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter();
}
}
} else if (second instanceof LSTORE) {
StoreInstruction secnd = (StoreInstruction) second;
if (first instanceof LLOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter();
}
}
} else if (second instanceof DSTORE) {
StoreInstruction secnd = (StoreInstruction) second;
if (first instanceof DLOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter();
}
}
} else if (second instanceof ReturnInstruction) {
// THIS APPLIES FOR RETURN TOO RIGHT?
// Replace store-return with return. Remember that upon return
// all local variables revert to their pre-call values, so any
// stores are destroyed.
if (first instanceof StoreInstruction) {
return new Filter(second);
}
} else if (second instanceof IADD) {
// Replace ineg-iadd with isub
if (first instanceof INEG) {
return new Filter(new ISUB());
}
} else if (second instanceof ISUB) {
// Replace ineg-isub with iadd
if (first instanceof INEG) {
return new Filter(new IADD());
}
} else if (second instanceof LADD) {
// Replace lneg-ladd with lsub
if (first instanceof LNEG) {
return new Filter(new LSUB());
}
} else if (second instanceof LSUB) {
// Replace lneg-lsub with ladd
if (first instanceof LNEG) {
return new Filter(new LADD());
}
} else if (second instanceof IF_ICMPEQ) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc 0-if_icmpeq with ifeq
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() == 0) {
return new Filter(new IFEQ(secnd.getTarget()));
}
}
}
} else if (second instanceof IF_ICMPNE) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc 0-if_icmpne with ifne
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() == 0) {
return new Filter(new IFNE(secnd.getTarget()));
}
}
}
} else if (second instanceof IF_ICMPLT) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc 0-if_icmplt with iflt
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() == 0) {
return new Filter(new IFLT(secnd.getTarget()));
}
}
}
} else if (second instanceof IF_ICMPGE) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc 0-if_icmpge with ifge
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() == 0) {
return new Filter(new IFGE(secnd.getTarget()));
}
}
}
} else if (second instanceof IF_ICMPGT) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc 0-if_icmpgt with ifgt
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() == 0) {
return new Filter(new IFGT(secnd.getTarget()));
}
}
}
} else if (second instanceof IF_ICMPLE) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc 0-if_icmple with ifle
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() == 0) {
return new Filter(new IFLE(secnd.getTarget()));
}
}
}
} else if (second instanceof IF_ACMPEQ) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc null-if_acmpeq with ifnull
if (first instanceof LDC) {
LDC frst = (LDC) first;
if (frst.getValue(method.getConstantPool()) == null) {
return new Filter(new IFNULL(secnd.getTarget()));
}
}
} else if (second instanceof IF_ACMPNE) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc null-if_acmpne with ifnonnull
if (first instanceof LDC) {
LDC frst = (LDC) first;
if (frst.getValue(method.getConstantPool()) == null) {
return new Filter(new IFNONNULL(secnd.getTarget()));
}
}
} else if (second instanceof IFEQ) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc 0-ifeq with goto and eliminate ldc !0-ifeq
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() == 0) {
return new Filter(new GOTO(secnd.getTarget()));
} else {
return new Filter();
}
}
}
} else if (second instanceof IFNE) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc !0-ifne with goto and eliminate ldc 0-ifne
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() != 0) {
return new Filter(new GOTO(secnd.getTarget()));
} else {
return new Filter();
}
}
}
} else if (second instanceof IFLT) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc <0-iflt with goto and eliminate ldc >=0-iflt
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() < 0) {
return new Filter(new GOTO(secnd.getTarget()));
} else {
return new Filter();
}
}
}
} else if (second instanceof IFGE) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc >=0-ifge with goto and eliminate ldc <0-ifge
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() >= 0) {
return new Filter(new GOTO(secnd.getTarget()));
} else {
return new Filter();
}
}
}
} else if (second instanceof IFGT) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc >0-ifgt with goto and eliminate ldc <=0-ifgt
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() > 0) {
return new Filter(new GOTO(secnd.getTarget()));
} else {
return new Filter();
}
}
}
} else if (second instanceof IFLE) {
BranchInstruction secnd = (BranchInstruction) second;
// Replace ldc <=0-ifle with goto and eliminate ldc >0-ifle
if (first instanceof LDC) {
LDC frst = (LDC) first;
Object op = frst.getValue(method.getConstantPool());
if (op instanceof Integer) {
if (((Integer) op).intValue() <= 0) {
return new Filter(new GOTO(secnd.getTarget()));
} else {
return new Filter();
}
}
}
}
if (second instanceof StoreInstruction) {
StoreInstruction secnd = (StoreInstruction) second;
// Replace store-store to same location with pop-store.
if (first instanceof StoreInstruction) {
StoreInstruction frst = (StoreInstruction) first;
if ((frst instanceof LSTORE) || (frst instanceof DSTORE)) {
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(new POP2(), first);
}
} else {
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(new POP(), first);
}
}
}
}
// Replace store-load with dup-store.
// Replace load-load with load-dup.
if (second instanceof ILOAD) {
LoadInstruction secnd = (LoadInstruction) second;
if (first instanceof ISTORE) {
StoreInstruction frst = (StoreInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(new DUP(), first);
}
}
if (first instanceof ILOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(first, new DUP());
}
}
} else if (second instanceof FLOAD) {
LoadInstruction secnd = (LoadInstruction) second;
if (first instanceof FSTORE) {
StoreInstruction frst = (StoreInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(new DUP(), first);
}
}
if (first instanceof FLOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(first, new DUP());
}
}
} else if (second instanceof ALOAD) {
LoadInstruction secnd = (LoadInstruction) second;
if (first instanceof ASTORE) {
StoreInstruction frst = (StoreInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(new DUP(), first);
}
}
if (first instanceof ALOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(first, new DUP());
}
}
} else if (second instanceof LLOAD) {
LoadInstruction secnd = (LoadInstruction) second;
if (first instanceof LSTORE) {
StoreInstruction frst = (StoreInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(new DUP2(), first);
}
}
if (first instanceof LLOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(first, new DUP2());
}
}
} else if (second instanceof DLOAD) {
LoadInstruction secnd = (LoadInstruction) second;
if (first instanceof DSTORE) {
StoreInstruction frst = (StoreInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(new DUP2(), first);
}
}
if (first instanceof DLOAD) {
LoadInstruction frst = (LoadInstruction) first;
if (frst.getIndex() == secnd.getIndex()) {
return new Filter(first, new DUP2());
}
}
}
return null;
}
}