use of de.mirkosertic.bytecoder.ssa.RegionNode in project Bytecoder by mirkosertic.
the class InlineGotoOptimizerTest method testSimpleFlow.
@Test
public void testSimpleFlow() {
Program theProgram = new Program();
ControlFlowGraph theGraph = theProgram.getControlFlowGraph();
RegionNode theNode = theGraph.createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
RegionNode theNode2 = theGraph.createAt(new BytecodeOpcodeAddress(20), RegionNode.BlockType.NORMAL);
theNode.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(20)));
theNode.addSuccessor(theNode2);
theNode2.getExpressions().add(new ReturnExpression());
theGraph.calculateReachabilityAndMarkBackEdges();
InlineGotoOptimizer theOptimizer = new InlineGotoOptimizer();
theOptimizer.optimize(theGraph, null);
Assert.assertEquals(1, theGraph.getKnownNodes().size(), 0);
Assert.assertEquals(1, theGraph.getDominatedNodes().size(), 0);
Assert.assertTrue(theGraph.getKnownNodes().contains(theNode));
Assert.assertEquals(1, theNode.getExpressions().size(), 0);
Assert.assertTrue(theNode.getExpressions().toList().get(0) instanceof ReturnExpression);
Assert.assertEquals(0, theNode.getSuccessors().size(), 0);
Relooper theRelooper = new Relooper();
Relooper.Block theRoot = theRelooper.reloop(theGraph);
}
use of de.mirkosertic.bytecoder.ssa.RegionNode in project Bytecoder by mirkosertic.
the class InlineGotoOptimizerTest method testIf.
@Test
public void testIf() {
Program theProgram = new Program();
ControlFlowGraph theGraph = theProgram.getControlFlowGraph();
RegionNode theNode = theGraph.createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
RegionNode theNode1 = theGraph.createAt(new BytecodeOpcodeAddress(20), RegionNode.BlockType.NORMAL);
RegionNode theNode2 = theGraph.createAt(new BytecodeOpcodeAddress(40), RegionNode.BlockType.NORMAL);
RegionNode theNode3 = theGraph.createAt(new BytecodeOpcodeAddress(60), RegionNode.BlockType.NORMAL);
theNode.addSuccessor(theNode1);
theNode.addSuccessor(theNode2);
ExpressionList theTrueClause = new ExpressionList();
theTrueClause.add(new GotoExpression(new BytecodeOpcodeAddress(20)));
IFExpression theIF = new IFExpression(new BytecodeOpcodeAddress(0), new BytecodeOpcodeAddress(20), new IntegerValue(10), theTrueClause);
theNode.getExpressions().add(theIF);
theNode.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(40)));
theNode1.addSuccessor(theNode3);
theNode1.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(60)));
theNode2.addSuccessor(theNode3);
theNode2.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(60)));
theNode3.getExpressions().add(new ReturnExpression());
theGraph.calculateReachabilityAndMarkBackEdges();
InlineGotoOptimizer theOptimizer = new InlineGotoOptimizer();
theOptimizer.optimize(theGraph, null);
System.out.println(theGraph.toDOT());
}
use of de.mirkosertic.bytecoder.ssa.RegionNode in project Bytecoder by mirkosertic.
the class RelooperTest method testEndlessLoop.
@Test
public void testEndlessLoop() {
Program theProgram = new Program();
ControlFlowGraph theGraph = new ControlFlowGraph(theProgram);
RegionNode theNode1 = theGraph.createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
theNode1.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(10)));
RegionNode theNode2 = theGraph.createAt(new BytecodeOpcodeAddress(10), RegionNode.BlockType.NORMAL);
theNode2.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(20)));
RegionNode theNode3 = theGraph.createAt(new BytecodeOpcodeAddress(20), RegionNode.BlockType.NORMAL);
theNode3.getExpressions().add(new GotoExpression(BytecodeOpcodeAddress.START_AT_ZERO));
theNode1.addSuccessor(theNode2);
theNode2.addSuccessor(theNode3);
theNode3.addSuccessor(theNode1);
theGraph.calculateReachabilityAndMarkBackEdges();
Relooper theRelooper = new Relooper();
Relooper.Block theBlock = theRelooper.reloop(theGraph);
theRelooper.debugPrint(System.out, theBlock);
}
use of de.mirkosertic.bytecoder.ssa.RegionNode in project Bytecoder by mirkosertic.
the class Relooper method replaceGotosIn.
private void replaceGotosIn(Stack<Block> aTraversalStack, Block aBlock) {
if (aBlock == null) {
return;
}
if (aBlock instanceof SimpleBlock) {
SimpleBlock theSimple = (SimpleBlock) aBlock;
aTraversalStack.push(theSimple);
RegionNode theInternalLabel = theSimple.internalLabel();
replaceGotosIn(aTraversalStack, theSimple, theInternalLabel, theInternalLabel.getExpressions());
replaceGotosIn(aTraversalStack, theSimple.next());
aTraversalStack.pop();
RegionNode theNode = theSimple.internalLabel;
Expression theLastExpression = theNode.getExpressions().lastExpression();
// can be silent, they only need to set the __label__ variable
if (theLastExpression instanceof BreakExpression) {
BreakExpression theBreak = (BreakExpression) theLastExpression;
if (Objects.equals(theBreak.blockToBreak().name(), theSimple.label().name())) {
theBreak.silent();
}
}
return;
}
if (aBlock instanceof LoopBlock) {
LoopBlock theLoop = (LoopBlock) aBlock;
aTraversalStack.push(theLoop);
replaceGotosIn(aTraversalStack, theLoop.inner());
replaceGotosIn(aTraversalStack, theLoop.next());
aTraversalStack.pop();
return;
}
if (aBlock instanceof MultipleBlock) {
MultipleBlock theMultiple = (MultipleBlock) aBlock;
aTraversalStack.push(theMultiple);
for (Block theHandler : theMultiple.handlers()) {
replaceGotosIn(aTraversalStack, theHandler);
}
replaceGotosIn(aTraversalStack, theMultiple.next());
aTraversalStack.pop();
return;
}
throw new IllegalStateException("Don't know how to handle " + aBlock);
}
use of de.mirkosertic.bytecoder.ssa.RegionNode in project Bytecoder by mirkosertic.
the class Relooper method replaceGotosIn.
private void replaceGotosIn(Stack<Block> aTraversalStack, SimpleBlock aCurrent, RegionNode aLabel, ExpressionList aList) {
for (Expression theExpression : aList.toList()) {
if (theExpression instanceof ExpressionListContainer) {
ExpressionListContainer theContainer = (ExpressionListContainer) theExpression;
for (ExpressionList theList : theContainer.getExpressionLists()) {
replaceGotosIn(aTraversalStack, aCurrent, aLabel, theList);
}
}
if (theExpression instanceof GotoExpression) {
GotoExpression theGoto = (GotoExpression) theExpression;
boolean theGotoFound = false;
// We search the successor edge
for (Map.Entry<RegionNode.Edge, RegionNode> theSuc : aLabel.getSuccessors().entrySet()) {
if (Objects.equals(theSuc.getValue().getStartAddress(), theGoto.getJumpTarget())) {
theGotoFound = true;
RegionNode theTarget = theSuc.getValue();
// We found the matching edge
if (theSuc.getKey().getType() == RegionNode.EdgeType.NORMAL) {
// We can only branch to the next block
// We search the whole hiararchy to find the right block to break out
boolean theSomethingFound = false;
for (int i = aTraversalStack.size() - 1; i >= 0; i--) {
Block theNestingBlock = aTraversalStack.get(i);
if (theNestingBlock.next() != null && theNestingBlock.next().entries().contains(theTarget)) {
theNestingBlock.requireLabel();
BreakExpression theBreak = new BreakExpression(theNestingBlock.label(), theTarget.getStartAddress());
aList.replace(theGoto, theBreak);
if (theNestingBlock.next() instanceof SimpleBlock && theNestingBlock.next().entries().size() == 1) {
theBreak.noSetRequired();
}
theSomethingFound = true;
break;
} else if (theNestingBlock.entries().contains(theTarget)) {
theNestingBlock.requireLabel();
ContinueExpression theContinue = new ContinueExpression(theNestingBlock.label(), theTarget.getStartAddress());
aList.replace(theGoto, theContinue);
theSomethingFound = true;
break;
}
}
if (!theSomethingFound) {
throw new IllegalStateException("Failed to jump to " + theTarget.getStartAddress().getAddress() + " from " + aCurrent.label().name() + " : no matching entry found!");
}
} else {
// We can only branch back into the known stack of nested blocks
boolean theSomethingFound = false;
for (Block theNestingBlock : aTraversalStack) {
if (theNestingBlock.entries().contains(theTarget)) {
theSomethingFound = true;
// We can return to the target in the hierarchy
theNestingBlock.requireLabel();
ContinueExpression theContinue = new ContinueExpression(theNestingBlock.label(), theTarget.getStartAddress());
aList.replace(theGoto, theContinue);
break;
}
}
if (!theSomethingFound) {
throw new IllegalStateException("No back edge target found for " + theTarget.getStartAddress().getAddress());
}
}
}
}
if (!theGotoFound) {
throw new IllegalStateException("No GOTO possible for " + theGoto.getJumpTarget().getAddress() + " in label " + aCurrent.label().name());
}
}
}
}
Aggregations