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

986 lines
39 KiB

18 years ago
/*
* 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 {
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
18 years ago
public static boolean DEBUG = false;
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
public String traceMessage(String dateString) {
18 years ago
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();
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
// BCEL - BLOAT means jumps can also be Labels.
if (FlowGraph.label(blockIter)) {
label = blockIter;
visited.add(label);
}
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
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;
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
} 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.
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
label = ((BranchInstruction) inst).getTarget();
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
if (!visited.contains(label)) {
visited.add(label);
stack.push(label);
}
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
// Fall through.
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
} else if (inst instanceof GotoInstruction) {
// Add next block to work list.
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
label = ((GotoInstruction) inst).getTarget();
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
if (!visited.contains(label)) {
visited.add(label);
stack.push(label);
}
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
break;
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
} else if (inst instanceof RET) {
// The ret targets were handled by the jsr.
break;
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
} else if (inst instanceof Select) {
// A switch. Add all possible targets of the switch to
// the worklist.
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
Select sw = (Select) inst;
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
label = sw.getTarget();
if (!visited.contains(label)) {
visited.add(label);
stack.push(label);
}
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
InstructionHandle[] targets = sw.getTargets();
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
for (int j = 0; j < targets.length; j++) {
label = targets[j];
18 years ago
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
if (!visited.contains(label)) {
visited.add(label);
stack.push(label);
}
18 years ago
}
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
break;
18 years ago
}
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
18 years ago
}
}
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);
}
BLOAT made use of a special instruction called a 'Label' this instruction denoted the target of a jump, exception handler, or the start and end of a try catch block (the start of a basic block). BCEL has no such instruction, however Labels can be emulated by setting a Label attribute to InstructionHandles and creating a NOP instruction. For Peephole this would work but I wanted to allow Peephole to be run on code that had not been generated using CodeGenerator. For this reason when calling transform on Peephole there is a flag to indicate whether Labels have been set or not. If Labels have not been set a call to FlowGraph.buildBLOATInstructionList(method) is performed. This only sets the Label attribute in InstructionHandles it does not create the NOP instructions. This means that Peephole code had to be changed to reflect the fact that a Label is also the first and also possibly the last instruction in a basic block. In the method Peephole.removeUnreachable(...) a block consisting of a single goto instruction caused an error, the code marking visited blocks did not take into account that the current instruction could be both a Label and a branch instruction, this lead to the target instruction not being included in the visited code and therefore being considered unreachable. This was solved by allowing the code to mark as visited an InstructionHandle with the Label attribute set and then go on to test if the same instruction was a branch instruction, and mark as visited any targets of the branch instruction. Previously the code tested if an instruction had the Label attribute set and if it did marked it as visited, if it did not it went on to test if the instruction was a branch instruction and marked as visited any target instructions.
18 years ago
try {
code.delete(ce);
} catch (TargetLostException lte) {
// do nothing if this is dead code there shouldn't be a
// targeter.
}
18 years ago
}
}
}
/**
* 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;
}
}