Search in sources :

Example 1 with GotoExpression

use of de.mirkosertic.bytecoder.ssa.GotoExpression 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);
}
Also used : ReturnExpression(de.mirkosertic.bytecoder.ssa.ReturnExpression) Program(de.mirkosertic.bytecoder.ssa.Program) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) Relooper(de.mirkosertic.bytecoder.relooper.Relooper) ControlFlowGraph(de.mirkosertic.bytecoder.ssa.ControlFlowGraph) BytecodeOpcodeAddress(de.mirkosertic.bytecoder.core.BytecodeOpcodeAddress) RegionNode(de.mirkosertic.bytecoder.ssa.RegionNode) Test(org.junit.Test)

Example 2 with GotoExpression

use of de.mirkosertic.bytecoder.ssa.GotoExpression 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());
}
Also used : ReturnExpression(de.mirkosertic.bytecoder.ssa.ReturnExpression) Program(de.mirkosertic.bytecoder.ssa.Program) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) ControlFlowGraph(de.mirkosertic.bytecoder.ssa.ControlFlowGraph) IntegerValue(de.mirkosertic.bytecoder.ssa.IntegerValue) BytecodeOpcodeAddress(de.mirkosertic.bytecoder.core.BytecodeOpcodeAddress) IFExpression(de.mirkosertic.bytecoder.ssa.IFExpression) RegionNode(de.mirkosertic.bytecoder.ssa.RegionNode) ExpressionList(de.mirkosertic.bytecoder.ssa.ExpressionList) Test(org.junit.Test)

Example 3 with GotoExpression

use of de.mirkosertic.bytecoder.ssa.GotoExpression 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);
}
Also used : Program(de.mirkosertic.bytecoder.ssa.Program) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) ControlFlowGraph(de.mirkosertic.bytecoder.ssa.ControlFlowGraph) BytecodeOpcodeAddress(de.mirkosertic.bytecoder.core.BytecodeOpcodeAddress) RegionNode(de.mirkosertic.bytecoder.ssa.RegionNode) Test(org.junit.Test)

Example 4 with GotoExpression

use of de.mirkosertic.bytecoder.ssa.GotoExpression in project Bytecoder by mirkosertic.

the class Relooper method debugPrint.

private void debugPrint(PrintStream aStream, int aInset, ExpressionList aExpressionList) {
    for (Expression theExpression : aExpressionList.toList()) {
        if (theExpression instanceof BreakExpression) {
            BreakExpression theBreak = (BreakExpression) theExpression;
            printInset(aStream, aInset);
            aStream.println("Break " + theBreak.blockToBreak().name() + " and jump to " + theBreak.jumpTarget().getAddress());
        } else if (theExpression instanceof ContinueExpression) {
            ContinueExpression theContinue = (ContinueExpression) theExpression;
            printInset(aStream, aInset);
            aStream.println("Continue at " + theContinue.labelToReturnTo().name());
        } else if (theExpression instanceof ReturnExpression) {
            printInset(aStream, aInset);
            aStream.println("Return");
        } else if (theExpression instanceof GotoExpression) {
            throw new IllegalStateException("Goto should have been removed!");
        }
    }
}
Also used : ReturnExpression(de.mirkosertic.bytecoder.ssa.ReturnExpression) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) ContinueExpression(de.mirkosertic.bytecoder.ssa.ContinueExpression) Expression(de.mirkosertic.bytecoder.ssa.Expression) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) ReturnExpression(de.mirkosertic.bytecoder.ssa.ReturnExpression) BreakExpression(de.mirkosertic.bytecoder.ssa.BreakExpression) ContinueExpression(de.mirkosertic.bytecoder.ssa.ContinueExpression) BreakExpression(de.mirkosertic.bytecoder.ssa.BreakExpression)

Example 5 with GotoExpression

use of de.mirkosertic.bytecoder.ssa.GotoExpression 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());
            }
        }
    }
}
Also used : BreakExpression(de.mirkosertic.bytecoder.ssa.BreakExpression) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) ContinueExpression(de.mirkosertic.bytecoder.ssa.ContinueExpression) Expression(de.mirkosertic.bytecoder.ssa.Expression) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) ReturnExpression(de.mirkosertic.bytecoder.ssa.ReturnExpression) BreakExpression(de.mirkosertic.bytecoder.ssa.BreakExpression) ContinueExpression(de.mirkosertic.bytecoder.ssa.ContinueExpression) ExpressionListContainer(de.mirkosertic.bytecoder.ssa.ExpressionListContainer) RegionNode(de.mirkosertic.bytecoder.ssa.RegionNode) ExpressionList(de.mirkosertic.bytecoder.ssa.ExpressionList) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

GotoExpression (de.mirkosertic.bytecoder.ssa.GotoExpression)13 RegionNode (de.mirkosertic.bytecoder.ssa.RegionNode)9 ReturnExpression (de.mirkosertic.bytecoder.ssa.ReturnExpression)9 BytecodeOpcodeAddress (de.mirkosertic.bytecoder.core.BytecodeOpcodeAddress)7 ControlFlowGraph (de.mirkosertic.bytecoder.ssa.ControlFlowGraph)6 Expression (de.mirkosertic.bytecoder.ssa.Expression)6 ExpressionList (de.mirkosertic.bytecoder.ssa.ExpressionList)6 Program (de.mirkosertic.bytecoder.ssa.Program)6 Test (org.junit.Test)6 BreakExpression (de.mirkosertic.bytecoder.ssa.BreakExpression)4 ContinueExpression (de.mirkosertic.bytecoder.ssa.ContinueExpression)4 ExpressionListContainer (de.mirkosertic.bytecoder.ssa.ExpressionListContainer)4 IFExpression (de.mirkosertic.bytecoder.ssa.IFExpression)3 Relooper (de.mirkosertic.bytecoder.relooper.Relooper)2 ArrayStoreExpression (de.mirkosertic.bytecoder.ssa.ArrayStoreExpression)2 CheckCastExpression (de.mirkosertic.bytecoder.ssa.CheckCastExpression)2 DirectInvokeMethodExpression (de.mirkosertic.bytecoder.ssa.DirectInvokeMethodExpression)2 IntegerValue (de.mirkosertic.bytecoder.ssa.IntegerValue)2 InvokeStaticMethodExpression (de.mirkosertic.bytecoder.ssa.InvokeStaticMethodExpression)2 InvokeVirtualMethodExpression (de.mirkosertic.bytecoder.ssa.InvokeVirtualMethodExpression)2