Search in sources :

Example 6 with LLVMBasicBlockNode

use of com.oracle.truffle.llvm.runtime.nodes.base.LLVMBasicBlockNode in project graal by oracle.

the class LLVMLoopDispatchNode method executeRepeatingWithValue.

/**
 * The code in this function is mirrored from {@link LLVMDispatchBasicBlockNode}, any changes
 * need to be done in both places. The block id of the successor block (where to continue after
 * the loop) is stored in a frame slot.
 */
@ExplodeLoop(kind = LoopExplosionKind.MERGE_EXPLODE)
@Override
public Object executeRepeatingWithValue(VirtualFrame frame) {
    CompilerAsserts.partialEvaluationConstant(bodyNodes.length);
    int basicBlockIndex = headerId;
    // do-while loop fails at PE
    outer: while (true) {
        CompilerAsserts.partialEvaluationConstant(basicBlockIndex);
        LLVMBasicBlockNode bb = bodyNodes[indexMapping[basicBlockIndex]];
        // lazily insert the basic block into the AST
        bb.initialize();
        // the newly inserted block may have been instrumented
        bb = bodyNodes[indexMapping[basicBlockIndex]];
        // execute all statements
        bb.execute(frame);
        // execute control flow node, write phis, null stack frame slots, and dispatch to
        // the correct successor block
        LLVMControlFlowNode controlFlowNode = bb.getTerminatingInstruction();
        if (controlFlowNode instanceof LLVMConditionalBranchNode) {
            LLVMConditionalBranchNode conditionalBranchNode = (LLVMConditionalBranchNode) controlFlowNode;
            boolean condition = conditionalBranchNode.executeCondition(frame);
            if (CompilerDirectives.injectBranchProbability(bb.getBranchProbability(LLVMConditionalBranchNode.TRUE_SUCCESSOR), condition)) {
                bb.enterSuccessor(LLVMConditionalBranchNode.TRUE_SUCCESSOR);
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                LLVMDispatchBasicBlockNode.executePhis(frame, conditionalBranchNode, LLVMConditionalBranchNode.TRUE_SUCCESSOR);
                basicBlockIndex = conditionalBranchNode.getTrueSuccessor();
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                if (basicBlockIndex == headerId) {
                    return RepeatingNode.CONTINUE_LOOP_STATUS;
                }
                if (!isInLoop(basicBlockIndex)) {
                    frame.setInt(successorSlot, basicBlockIndex);
                    return RepeatingNode.BREAK_LOOP_STATUS;
                }
                continue outer;
            } else {
                bb.enterSuccessor(LLVMConditionalBranchNode.FALSE_SUCCESSOR);
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                LLVMDispatchBasicBlockNode.executePhis(frame, conditionalBranchNode, LLVMConditionalBranchNode.FALSE_SUCCESSOR);
                basicBlockIndex = conditionalBranchNode.getFalseSuccessor();
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                if (basicBlockIndex == headerId) {
                    return RepeatingNode.CONTINUE_LOOP_STATUS;
                }
                if (!isInLoop(basicBlockIndex)) {
                    frame.setInt(successorSlot, basicBlockIndex);
                    return RepeatingNode.BREAK_LOOP_STATUS;
                }
                continue outer;
            }
        } else if (controlFlowNode instanceof LLVMSwitchNode) {
            LLVMSwitchNode switchNode = (LLVMSwitchNode) controlFlowNode;
            Object condition = switchNode.executeCondition(frame);
            int[] successors = switchNode.getSuccessors();
            for (int i = 0; i < successors.length - 1; i++) {
                if (CompilerDirectives.injectBranchProbability(bb.getBranchProbability(i), switchNode.checkCase(frame, i, condition))) {
                    bb.enterSuccessor(i);
                    LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                    LLVMDispatchBasicBlockNode.executePhis(frame, switchNode, i);
                    basicBlockIndex = successors[i];
                    LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                    if (basicBlockIndex == headerId) {
                        return RepeatingNode.CONTINUE_LOOP_STATUS;
                    }
                    if (!isInLoop(basicBlockIndex)) {
                        frame.setInt(successorSlot, basicBlockIndex);
                        return RepeatingNode.BREAK_LOOP_STATUS;
                    }
                    continue outer;
                }
            }
            int i = successors.length - 1;
            bb.enterSuccessor(i);
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
            LLVMDispatchBasicBlockNode.executePhis(frame, switchNode, i);
            basicBlockIndex = successors[i];
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
            if (basicBlockIndex == headerId) {
                return RepeatingNode.CONTINUE_LOOP_STATUS;
            }
            if (!isInLoop(basicBlockIndex)) {
                frame.setInt(successorSlot, basicBlockIndex);
                return RepeatingNode.BREAK_LOOP_STATUS;
            }
            continue outer;
        } else if (controlFlowNode instanceof LLVMLoopNode) {
            LLVMLoopNode loop = (LLVMLoopNode) controlFlowNode;
            loop.executeLoop(frame);
            int successorBasicBlockIndex = frame.getInt(successorSlot);
            // null frame
            frame.setInt(successorSlot, 0);
            int[] successors = loop.getSuccessors();
            for (int i = 0; i < successors.length - 1; i++) {
                if (successorBasicBlockIndex == successors[i]) {
                    basicBlockIndex = successors[i];
                    if (basicBlockIndex == headerId) {
                        return RepeatingNode.CONTINUE_LOOP_STATUS;
                    }
                    if (!isInLoop(basicBlockIndex)) {
                        frame.setInt(successorSlot, basicBlockIndex);
                        return RepeatingNode.BREAK_LOOP_STATUS;
                    }
                    continue outer;
                }
            }
            int i = successors.length - 1;
            assert successors[i] == successorBasicBlockIndex : "Could not find loop successor!";
            basicBlockIndex = successors[i];
            if (basicBlockIndex == headerId) {
                return RepeatingNode.CONTINUE_LOOP_STATUS;
            }
            if (!isInLoop(basicBlockIndex)) {
                frame.setInt(successorSlot, basicBlockIndex);
                return RepeatingNode.BREAK_LOOP_STATUS;
            }
            continue outer;
        } else if (controlFlowNode instanceof LLVMIndirectBranchNode) {
            // TODO (chaeubl): we need a different approach here - this is awfully
            // inefficient (see GR-3664)
            LLVMIndirectBranchNode indirectBranchNode = (LLVMIndirectBranchNode) controlFlowNode;
            int[] successors = indirectBranchNode.getSuccessors();
            int successorBasicBlockIndex = indirectBranchNode.executeCondition(frame);
            for (int i = 0; i < successors.length - 1; i++) {
                if (CompilerDirectives.injectBranchProbability(bb.getBranchProbability(i), successors[i] == successorBasicBlockIndex)) {
                    bb.enterSuccessor(i);
                    LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                    LLVMDispatchBasicBlockNode.executePhis(frame, indirectBranchNode, i);
                    basicBlockIndex = successors[i];
                    LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                    if (basicBlockIndex == headerId) {
                        return RepeatingNode.CONTINUE_LOOP_STATUS;
                    }
                    if (!isInLoop(basicBlockIndex)) {
                        frame.setInt(successorSlot, basicBlockIndex);
                        return RepeatingNode.BREAK_LOOP_STATUS;
                    }
                    continue outer;
                }
            }
            int i = successors.length - 1;
            assert successorBasicBlockIndex == successors[i];
            bb.enterSuccessor(i);
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
            LLVMDispatchBasicBlockNode.executePhis(frame, indirectBranchNode, i);
            basicBlockIndex = successors[i];
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
            if (basicBlockIndex == headerId) {
                return RepeatingNode.CONTINUE_LOOP_STATUS;
            }
            if (!isInLoop(basicBlockIndex)) {
                frame.setInt(successorSlot, basicBlockIndex);
                return RepeatingNode.BREAK_LOOP_STATUS;
            }
            continue outer;
        } else if (controlFlowNode instanceof LLVMBrUnconditionalNode) {
            LLVMBrUnconditionalNode unconditionalNode = (LLVMBrUnconditionalNode) controlFlowNode;
            // required for instrumentation
            unconditionalNode.execute(frame);
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
            LLVMDispatchBasicBlockNode.executePhis(frame, unconditionalNode, 0);
            basicBlockIndex = unconditionalNode.getSuccessor();
            LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
            if (basicBlockIndex == headerId) {
                return RepeatingNode.CONTINUE_LOOP_STATUS;
            }
            if (!isInLoop(basicBlockIndex)) {
                frame.setInt(successorSlot, basicBlockIndex);
                return RepeatingNode.BREAK_LOOP_STATUS;
            }
            continue outer;
        } else if (controlFlowNode instanceof LLVMInvokeNode) {
            LLVMInvokeNode invokeNode = (LLVMInvokeNode) controlFlowNode;
            try {
                invokeNode.execute(frame);
                bb.enterSuccessor(LLVMInvokeNode.NORMAL_SUCCESSOR);
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                LLVMDispatchBasicBlockNode.executePhis(frame, invokeNode, LLVMInvokeNode.NORMAL_SUCCESSOR);
                basicBlockIndex = invokeNode.getNormalSuccessor();
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                if (basicBlockIndex == headerId) {
                    return RepeatingNode.CONTINUE_LOOP_STATUS;
                }
                if (!isInLoop(basicBlockIndex)) {
                    frame.setInt(successorSlot, basicBlockIndex);
                    return RepeatingNode.BREAK_LOOP_STATUS;
                }
                continue outer;
            } catch (LLVMUserException e) {
                bb.enterSuccessor(LLVMInvokeNode.UNWIND_SUCCESSOR);
                frame.setObject(exceptionValueSlot, e);
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, bb.nullableAfter);
                LLVMDispatchBasicBlockNode.executePhis(frame, invokeNode, LLVMInvokeNode.UNWIND_SUCCESSOR);
                basicBlockIndex = invokeNode.getUnwindSuccessor();
                LLVMDispatchBasicBlockNode.nullDeadSlots(frame, originalBodyNodes[basicBlockIndex].nullableBefore);
                if (basicBlockIndex == headerId) {
                    return RepeatingNode.CONTINUE_LOOP_STATUS;
                }
                if (!isInLoop(basicBlockIndex)) {
                    frame.setInt(successorSlot, basicBlockIndex);
                    return RepeatingNode.BREAK_LOOP_STATUS;
                }
                continue outer;
            }
        } else {
            // some control flow nodes should be never part of a loop
            CompilerDirectives.transferToInterpreterAndInvalidate();
            throw new UnsupportedOperationException("unexpected controlFlowNode type: " + controlFlowNode);
        }
    }
}
Also used : LLVMControlFlowNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode) LLVMInvokeNode(com.oracle.truffle.llvm.runtime.nodes.func.LLVMInvokeNode) LLVMUserException(com.oracle.truffle.llvm.runtime.except.LLVMUserException) LLVMBasicBlockNode(com.oracle.truffle.llvm.runtime.nodes.base.LLVMBasicBlockNode) ExplodeLoop(com.oracle.truffle.api.nodes.ExplodeLoop)

Aggregations

LLVMBasicBlockNode (com.oracle.truffle.llvm.runtime.nodes.base.LLVMBasicBlockNode)6 LLVMControlFlowNode (com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode)3 ArrayList (java.util.ArrayList)3 ExplodeLoop (com.oracle.truffle.api.nodes.ExplodeLoop)2 LLVMSourceLocation (com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation)2 LLVMUserException (com.oracle.truffle.llvm.runtime.except.LLVMUserException)2 LLVMStatementNode (com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode)2 LLVMInvokeNode (com.oracle.truffle.llvm.runtime.nodes.func.LLVMInvokeNode)2 FrameDescriptor (com.oracle.truffle.api.frame.FrameDescriptor)1 RepeatingNode (com.oracle.truffle.api.nodes.RepeatingNode)1 RootNode (com.oracle.truffle.api.nodes.RootNode)1 SourceSection (com.oracle.truffle.api.source.SourceSection)1 LLVMLivenessAnalysisResult (com.oracle.truffle.llvm.parser.LLVMLivenessAnalysis.LLVMLivenessAnalysisResult)1 Phi (com.oracle.truffle.llvm.parser.LLVMPhiManager.Phi)1 SourceVariable (com.oracle.truffle.llvm.parser.metadata.debuginfo.SourceVariable)1 InstructionBlock (com.oracle.truffle.llvm.parser.model.blocks.InstructionBlock)1 FunctionParameter (com.oracle.truffle.llvm.parser.model.functions.FunctionParameter)1 LLVMBitcodeInstructionVisitor (com.oracle.truffle.llvm.parser.nodes.LLVMBitcodeInstructionVisitor)1 LLVMRuntimeDebugInformation (com.oracle.truffle.llvm.parser.nodes.LLVMRuntimeDebugInformation)1 LLVMSymbolReadResolver (com.oracle.truffle.llvm.parser.nodes.LLVMSymbolReadResolver)1